@ventlio/tanstack-query 0.2.86 → 0.2.89

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 (37) hide show
  1. package/dist/config/useQueryConfig.js +27 -1
  2. package/dist/config/useQueryConfig.js.map +1 -1
  3. package/dist/config/useQueryHeaders.js +4 -15
  4. package/dist/config/useQueryHeaders.js.map +1 -1
  5. package/dist/config/useReactNativeEnv.js +3 -3
  6. package/dist/index.mjs +261 -111
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/model/useKeyTrackerModel.d.ts +1 -1
  9. package/dist/model/useKeyTrackerModel.js +5 -1
  10. package/dist/model/useKeyTrackerModel.js.map +1 -1
  11. package/dist/queries/useDeleteRequest.d.ts +4 -4
  12. package/dist/queries/useDeleteRequest.js +46 -19
  13. package/dist/queries/useDeleteRequest.js.map +1 -1
  14. package/dist/queries/useGetInfiniteRequest.d.ts +4 -4
  15. package/dist/queries/useGetInfiniteRequest.js +43 -20
  16. package/dist/queries/useGetInfiniteRequest.js.map +1 -1
  17. package/dist/queries/useGetRequest.d.ts +8 -8
  18. package/dist/queries/useGetRequest.js +48 -24
  19. package/dist/queries/useGetRequest.js.map +1 -1
  20. package/dist/queries/usePatchRequest.d.ts +8 -8
  21. package/dist/queries/usePatchRequest.js +48 -15
  22. package/dist/queries/usePatchRequest.js.map +1 -1
  23. package/dist/queries/usePostRequest.d.ts +4 -4
  24. package/dist/queries/usePostRequest.js +42 -14
  25. package/dist/queries/usePostRequest.js.map +1 -1
  26. package/dist/types/index.d.ts +15 -6
  27. package/package.json +1 -1
  28. package/src/config/useQueryConfig.ts +41 -4
  29. package/src/config/useQueryHeaders.ts +6 -18
  30. package/src/config/useReactNativeEnv.ts +3 -3
  31. package/src/model/useKeyTrackerModel.ts +5 -1
  32. package/src/queries/useDeleteRequest.ts +51 -23
  33. package/src/queries/useGetInfiniteRequest.ts +48 -24
  34. package/src/queries/useGetRequest.ts +53 -29
  35. package/src/queries/usePatchRequest.ts +52 -18
  36. package/src/queries/usePostRequest.ts +46 -17
  37. package/src/types/index.ts +11 -6
@@ -1,8 +1,7 @@
1
1
  import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query';
3
3
  import { startTransition, useEffect, useMemo, useState } from 'react';
4
- import type { RawAxiosRequestHeaders } from '../../node_modules/axios/index';
5
- import { useEnvironmentVariables, useQueryHeaders } from '../config';
4
+ import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../config';
6
5
 
7
6
  import type { IRequestError, IRequestSuccess } from '../request';
8
7
  import { makeRequest } from '../request';
@@ -21,12 +20,14 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
21
20
  queryOptions?: TanstackQueryOption<TResponse>;
22
21
  keyTracker?: string;
23
22
  } & DefaultRequestOptions) => {
24
- const [requestPath, updatePath] = useState<string>(path);
23
+ const [requestPath, setRequestPath] = useState<string>(path);
25
24
  const [options, setOptions] = useState<any>(queryOptions);
26
25
  const [page, setPage] = useState<number>(1);
27
26
 
28
27
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
29
28
  const { getHeaders } = useQueryHeaders();
29
+ const { options: queryConfigOptions, setConfig } = useQueryConfig();
30
+ const [queryConfig, setQueryConfig] = useState<{ link: string; fetchOptions: any }>();
30
31
 
31
32
  let queryClient = useQueryClient();
32
33
 
@@ -38,25 +39,38 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
38
39
  value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
39
40
  ) => void,
40
41
  rej: (reason?: any) => void,
41
- queryKey?: QueryKey
42
+ queryKey: QueryKey
42
43
  ) => {
43
44
  if (load) {
44
45
  // get request headers
45
- const globalHeaders: RawAxiosRequestHeaders = getHeaders();
46
+ const globalHeaders = getHeaders();
46
47
 
47
- const [url] = (queryKey ?? []) as string[];
48
+ const [url] = queryKey;
49
+ const requestUrl = (url ?? requestPath) as string;
48
50
 
49
- const getResponse = await makeRequest<TResponse>({
50
- path: url ?? requestPath,
51
+ const requestOptions = {
52
+ path: requestUrl,
51
53
  headers: { ...globalHeaders, ...headers },
52
54
  baseURL: baseUrl ?? API_URL,
53
55
  timeout: TIMEOUT,
54
- });
56
+ };
55
57
 
56
- if (getResponse.status) {
57
- res(getResponse as IRequestSuccess<TResponse>);
58
+ let shouldContinue = true;
59
+
60
+ if (queryConfigOptions.queryMiddleware) {
61
+ shouldContinue = await queryConfigOptions.queryMiddleware({ queryKey, ...requestOptions });
62
+ }
63
+
64
+ if (shouldContinue) {
65
+ const getResponse = await makeRequest<TResponse>(requestOptions);
66
+
67
+ if (getResponse.status) {
68
+ res(getResponse as IRequestSuccess<TResponse>);
69
+ } else {
70
+ rej(getResponse);
71
+ }
58
72
  } else {
59
- rej(getResponse);
73
+ rej(null);
60
74
  }
61
75
  } else {
62
76
  res(null as any);
@@ -75,27 +89,22 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
75
89
 
76
90
  useEffect(() => {
77
91
  if (path) {
78
- updatePath(path);
92
+ setRequestPath(path);
79
93
  }
80
94
  }, [path]);
81
95
 
82
96
  useEffect(() => {
83
97
  if (keyTracker) {
84
- // set expiration time for the tracker
85
- queryClient.setQueryDefaults([keyTracker], {
86
- cacheTime: Infinity,
87
- staleTime: Infinity,
88
- });
89
-
90
- queryClient.setQueryData([keyTracker], [requestPath, {}]);
98
+ setConfig({ [keyTracker]: [requestPath, {}] });
91
99
  }
92
- }, [keyTracker, requestPath, queryClient, queryOptions?.staleTime]);
100
+ // eslint-disable-next-line react-hooks/exhaustive-deps
101
+ }, [keyTracker, requestPath]);
93
102
 
94
103
  const nextPage = () => {
95
104
  if (query.data?.data.pagination) {
96
105
  const pagination: IPagination = query.data.data.pagination;
97
106
  if (pagination.next_page !== pagination.current_page && pagination.next_page > pagination.current_page) {
98
- updatePath(constructPaginationLink(requestPath, pagination.next_page));
107
+ setRequestPath(constructPaginationLink(requestPath, pagination.next_page));
99
108
  }
100
109
  }
101
110
  };
@@ -104,7 +113,7 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
104
113
  if (query.data?.data.pagination) {
105
114
  const pagination: IPagination = query.data.data.pagination;
106
115
  if (pagination.previous_page !== pagination.current_page && pagination.previous_page < pagination.current_page) {
107
- updatePath(constructPaginationLink(requestPath, pagination.previous_page));
116
+ setRequestPath(constructPaginationLink(requestPath, pagination.previous_page));
108
117
  }
109
118
  }
110
119
  };
@@ -127,12 +136,12 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
127
136
  };
128
137
 
129
138
  const gotoPage = (pageNumber: number) => {
130
- updatePath(constructPaginationLink(requestPath, pageNumber));
139
+ setRequestPath(constructPaginationLink(requestPath, pageNumber));
131
140
  };
132
141
 
133
142
  const updatedPathAsync = async (link: string) => {
134
143
  startTransition(() => {
135
- updatePath(link);
144
+ setRequestPath(link);
136
145
  });
137
146
  };
138
147
 
@@ -151,15 +160,30 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
151
160
  Array<any>
152
161
  >
153
162
  ): Promise<IRequestSuccess<TResponse> | undefined> => {
154
- await setOptionsAsync(fetchOptions);
155
- await updatedPathAsync(link);
163
+ if (!queryConfigOptions.pauseFutureQueries) {
164
+ await setOptionsAsync(fetchOptions);
165
+ await updatedPathAsync(link);
156
166
 
157
- return query.data;
167
+ return query.data;
168
+ } else {
169
+ setQueryConfig({ link, fetchOptions });
170
+
171
+ return undefined;
172
+ }
158
173
  };
159
174
 
175
+ useEffect(() => {
176
+ if (!queryConfigOptions.pauseFutureQueries && queryConfig) {
177
+ get(queryConfig.link, queryConfig.fetchOptions);
178
+ setQueryConfig(undefined);
179
+ }
180
+ // eslint-disable-next-line react-hooks/exhaustive-deps
181
+ }, [queryConfigOptions.pauseFutureQueries]);
182
+
160
183
  return {
161
184
  ...query,
162
- updatePath,
185
+ isLoading: query.isLoading || queryConfigOptions.pauseFutureQueries,
186
+ setRequestPath,
163
187
  nextPage,
164
188
  prevPage,
165
189
  get,
@@ -1,6 +1,6 @@
1
1
  import type { MutateOptions } from '@tanstack/react-query';
2
2
  import { useMutation } from '@tanstack/react-query';
3
- import type { RawAxiosRequestHeaders } from 'axios';
3
+ import { useEffect, useState } from 'react';
4
4
  import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../config';
5
5
  import { scrollToTop } from '../helpers';
6
6
  import { useUploadProgress } from '../hooks';
@@ -11,6 +11,7 @@ import type { DefaultRequestOptions } from './queries.interface';
11
11
  export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: string } & DefaultRequestOptions) => {
12
12
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
13
13
  const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
14
+ const [mutationConfig, setMutationConfig] = useState<{ data: any; options: any }>();
14
15
 
15
16
  const { getHeaders } = useQueryHeaders();
16
17
 
@@ -18,9 +19,9 @@ export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: s
18
19
 
19
20
  const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void, data: any) => {
20
21
  // get request headers
21
- const globalHeaders: RawAxiosRequestHeaders = getHeaders();
22
+ const globalHeaders = getHeaders();
22
23
 
23
- const patchResponse = await makeRequest<TResponse>({
24
+ const requestOptions = {
24
25
  path: path,
25
26
  body: data,
26
27
  method: HttpMethod.PATCH,
@@ -28,20 +29,34 @@ export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: s
28
29
  baseURL: baseUrl ?? API_URL,
29
30
  timeout: TIMEOUT,
30
31
  onUploadProgress,
31
- });
32
+ };
32
33
 
33
- if (patchResponse.status) {
34
- // scroll to top after success
35
- if (config.options?.context !== 'app') {
36
- scrollToTop();
34
+ let shouldContinue = true;
35
+
36
+ if (config.options.mutationMiddleware) {
37
+ shouldContinue = await config.options.mutationMiddleware({
38
+ mutationKey: [path, { type: 'mutation' }],
39
+ ...requestOptions,
40
+ });
41
+ }
42
+
43
+ if (shouldContinue) {
44
+ const patchResponse = await makeRequest<TResponse>(requestOptions);
45
+ if (patchResponse.status) {
46
+ // scroll to top after success
47
+ if (config.options.context !== 'app') {
48
+ scrollToTop();
49
+ }
50
+ res(patchResponse as IRequestSuccess<TResponse>);
51
+ } else {
52
+ // scroll to top after error
53
+ if (config.options.context !== 'app') {
54
+ scrollToTop();
55
+ }
56
+ rej(patchResponse);
37
57
  }
38
- res(patchResponse as IRequestSuccess<TResponse>);
39
58
  } else {
40
- // scroll to top after error
41
- if (config.options?.context !== 'app') {
42
- scrollToTop();
43
- }
44
- rej(patchResponse);
59
+ rej(null);
45
60
  }
46
61
  };
47
62
 
@@ -50,15 +65,34 @@ export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: s
50
65
  (dataData: any) =>
51
66
  new Promise<IRequestSuccess<TResponse>>((res, rej) => {
52
67
  return sendRequest(res, rej, dataData);
53
- })
68
+ }),
69
+ { mutationKey: [path, { type: 'mutation' }] }
54
70
  );
55
71
 
56
72
  const patch = async (
57
73
  data: any,
58
74
  options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined
59
- ): Promise<IRequestSuccess<TResponse>> => {
60
- return mutation.mutateAsync(data, options);
75
+ ): Promise<IRequestSuccess<TResponse> | undefined> => {
76
+ if (!config.options.pauseFutureMutations) {
77
+ return mutation.mutateAsync(data, options);
78
+ } else {
79
+ setMutationConfig({ data, options });
80
+ return undefined;
81
+ }
61
82
  };
62
83
 
63
- return { patch, uploadProgressPercent, ...mutation };
84
+ useEffect(() => {
85
+ if (!config.options.pauseFutureMutations && mutationConfig) {
86
+ patch(mutationConfig.data, mutationConfig.options);
87
+ setMutationConfig(undefined);
88
+ }
89
+ // eslint-disable-next-line react-hooks/exhaustive-deps
90
+ }, [config.options.pauseFutureMutations]);
91
+
92
+ return {
93
+ patch,
94
+ uploadProgressPercent,
95
+ ...mutation,
96
+ isLoading: mutation.isLoading || config.options.pauseFutureMutations,
97
+ };
64
98
  };
@@ -2,7 +2,7 @@ import type { MutateOptions } from '@tanstack/react-query';
2
2
  import { useMutation } from '@tanstack/react-query';
3
3
  import { useEnvironmentVariables, useQueryConfig, useQueryHeaders, useReactNativeEnv } from '../config';
4
4
 
5
- import type { RawAxiosRequestHeaders } from 'axios';
5
+ import { useEffect, useState } from 'react';
6
6
  import { scrollToTop } from '../helpers';
7
7
  import { useUploadProgress } from '../hooks';
8
8
  import type { IMakeRequest, IRequestError, IRequestSuccess } from '../request';
@@ -23,6 +23,7 @@ export const usePostRequest = <TResponse>({
23
23
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
24
24
 
25
25
  const config = useQueryConfig();
26
+ const [mutationConfig, setMutationConfig] = useState<{ data: any; options: any }>();
26
27
 
27
28
  const { getHeaders } = useQueryHeaders();
28
29
  const { isApp } = useReactNativeEnv();
@@ -34,13 +35,13 @@ export const usePostRequest = <TResponse>({
34
35
  postData: { data: any; requestConfig?: Partial<IMakeRequest> }
35
36
  ) => {
36
37
  // get request headers
37
- const globalHeaders: RawAxiosRequestHeaders = getHeaders();
38
+ const globalHeaders = getHeaders();
38
39
 
39
40
  const { data, requestConfig } = postData;
40
41
 
41
42
  delete requestConfig?.body;
42
43
 
43
- const postResponse = await makeRequest<TResponse>({
44
+ const requestOptions = {
44
45
  path,
45
46
  body: data,
46
47
  method: HttpMethod.POST,
@@ -54,21 +55,36 @@ export const usePostRequest = <TResponse>({
54
55
  },
55
56
  onUploadProgress,
56
57
  ...requestConfig,
57
- });
58
+ };
58
59
 
59
- if (postResponse.status) {
60
- // scroll to top after success
60
+ let shouldContinue = true;
61
61
 
62
- if (config.options?.context !== 'app') {
63
- scrollToTop();
62
+ if (config.options.mutationMiddleware) {
63
+ shouldContinue = await config.options.mutationMiddleware({
64
+ mutationKey: [path, { type: 'mutation' }],
65
+ ...requestOptions,
66
+ });
67
+ }
68
+
69
+ if (shouldContinue) {
70
+ const postResponse = await makeRequest<TResponse>(requestOptions);
71
+
72
+ if (postResponse.status) {
73
+ // scroll to top after success
74
+
75
+ if (config.options.context !== 'app') {
76
+ scrollToTop();
77
+ }
78
+ res(postResponse as IRequestSuccess<TResponse>);
79
+ } else {
80
+ // scroll to top after error
81
+ if (config.options.context !== 'app') {
82
+ scrollToTop();
83
+ }
84
+ rej(postResponse);
64
85
  }
65
- res(postResponse as IRequestSuccess<TResponse>);
66
86
  } else {
67
- // scroll to top after error
68
- if (config.options?.context !== 'app') {
69
- scrollToTop();
70
- }
71
- rej(postResponse);
87
+ rej(null);
72
88
  }
73
89
  };
74
90
 
@@ -93,10 +109,23 @@ export const usePostRequest = <TResponse>({
93
109
  | { requestConfig?: Partial<Omit<IMakeRequest, 'body'>> }
94
110
  | undefined
95
111
  ) & { requestConfig?: Partial<Omit<IMakeRequest, 'body'>> }
96
- ): Promise<IRequestSuccess<TResponse>> => {
97
- const { requestConfig, ...otherOptions } = options ?? {};
98
- return mutation.mutateAsync({ data, requestConfig }, otherOptions);
112
+ ): Promise<IRequestSuccess<TResponse> | undefined> => {
113
+ if (!config.options.pauseFutureMutations) {
114
+ const { requestConfig, ...otherOptions } = options ?? {};
115
+ return mutation.mutateAsync({ data, requestConfig }, otherOptions);
116
+ } else {
117
+ setMutationConfig({ data, options });
118
+ return undefined;
119
+ }
99
120
  };
100
121
 
122
+ useEffect(() => {
123
+ if (!config.options.pauseFutureMutations && mutationConfig) {
124
+ post(mutationConfig.data, mutationConfig.options);
125
+ setMutationConfig(undefined);
126
+ }
127
+ // eslint-disable-next-line react-hooks/exhaustive-deps
128
+ }, [config.options.pauseFutureMutations]);
129
+
101
130
  return { post, uploadProgressPercent, ...mutation };
102
131
  };
@@ -1,4 +1,6 @@
1
+ import type { QueryKey } from '@tanstack/react-query';
1
2
  import type { RawAxiosRequestHeaders } from 'axios';
3
+ import type { IMakeRequest } from '../request';
2
4
 
3
5
  export interface BootstrapConfig {
4
6
  environments?: {
@@ -7,8 +9,11 @@ export interface BootstrapConfig {
7
9
  };
8
10
  context?: ContextType;
9
11
  modelConfig?: BootstrapModelConfig;
10
- mutationMiddleware?: (mutateRequest?: any, mutateResponse?: any) => Promise<boolean>;
11
- queryMiddleware?: (queryRequest?: any, queryResponse?: any) => Promise<boolean>;
12
+ mutationMiddleware?: (mutateRequestConfig?: IMakeRequest & { mutationKey: QueryKey }) => Promise<boolean>;
13
+ queryMiddleware?: (queryRequestConfig?: IMakeRequest & { queryKey: QueryKey }) => Promise<boolean>;
14
+ pauseFutureMutations?: boolean;
15
+ pauseFutureQueries?: boolean;
16
+ headers?: RawAxiosRequestHeaders;
12
17
  }
13
18
 
14
19
  export interface BootstrapModelConfig {
@@ -17,11 +22,11 @@ export interface BootstrapModelConfig {
17
22
 
18
23
  export type ContextType = 'app' | 'web' | 'electronjs';
19
24
  export interface TanstackQueryConfig {
20
- headers: RawAxiosRequestHeaders;
21
- options?: BootstrapConfig;
25
+ options: BootstrapConfig;
26
+ setConfig: (options: BootstrapConfig) => void;
22
27
  }
23
28
 
24
29
  export interface IUseQueryHeaders {
25
- getHeaders: () => TanstackQueryConfig['headers'];
26
- setQueryHeaders: (header: TanstackQueryConfig['headers']) => void;
30
+ getHeaders: () => BootstrapConfig['headers'];
31
+ setQueryHeaders: (header: BootstrapConfig['headers']) => void;
27
32
  }