@ventlio/tanstack-query 0.2.73 → 0.2.74

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/README.md CHANGED
@@ -18,9 +18,11 @@ But we were not discouraged. So, we set out to find a solution which led to the
18
18
  - [✅] Requests context implementations
19
19
  - [✅] Post, Get, Patch Requests
20
20
  - [✅] Query key tracker to track dynamic query and help fetch query cache from any page
21
- - [Not Completed] Persistent queries implementation
21
+ - [] Persistent queries implementation (Not completed)
22
22
  - [❌] Put request
23
23
  - [❌] Generic return type (this is currently an issue if the API does not return object with the necessary properties required by the library)
24
+ - [❌] Generic Pagination for any response without infinite queries
25
+ - [❌] Infinite Get Query implementation (still using implementation meant for our use case)
24
26
  - [❌] Server sent events
25
27
  - [❌] Socket implementations
26
28
  - [❌] Tests
@@ -299,10 +301,11 @@ import { usePatchRequest } from '@ventlio/tanstack-query';
299
301
 
300
302
  function App() {
301
303
  const { patch, isLoading, isError, isSuccess, data } =
302
- usePatchRequest<User>(
304
+ usePatchRequest <
305
+ User >
303
306
  {
304
307
  path: '/users/1',
305
- });
308
+ };
306
309
 
307
310
  const updateUser = async (user: User) => {
308
311
  await patch(user);
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export { useKeyTrackerModel } from './model/useKeyTrackerModel.js';
9
9
  export { useQueryModel } from './model/useQueryModel.js';
10
10
  export { useRefetchQuery } from './model/useRefetchQuery.js';
11
11
  export { useDeleteRequest } from './queries/useDeleteRequest.js';
12
+ export { useGetInfiniteRequest } from './queries/useGetInfiniteRequest.js';
12
13
  export { useGetRequest } from './queries/useGetRequest.js';
13
14
  export { usePatchRequest } from './queries/usePatchRequest.js';
14
15
  export { usePostRequest } from './queries/usePostRequest.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import 'url-search-params-polyfill';
2
- import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
2
+ import { useQueryClient, useQuery, useInfiniteQuery, useMutation } from '@tanstack/react-query';
3
3
  import result from 'lodash.result';
4
4
  import lodashSet from 'lodash.set';
5
5
  import { useState, useMemo, useEffect, startTransition } from 'react';
@@ -396,11 +396,12 @@ const useDeleteRequest = (deleteOptions) => {
396
396
  const [options, setOptions] = useState();
397
397
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
398
398
  const { getHeaders } = useQueryHeaders();
399
- const sendRequest = async (res, rej) => {
399
+ const sendRequest = async (res, rej, queryKey) => {
400
400
  // get request headers
401
401
  const globalHeaders = getHeaders();
402
+ const [url] = (queryKey ?? []);
402
403
  const postResponse = await makeRequest({
403
- path: requestPath,
404
+ path: url ?? requestPath,
404
405
  headers: { ...globalHeaders, ...headers },
405
406
  method: HttpMethod.DELETE,
406
407
  baseURL: baseUrl ?? API_URL,
@@ -413,7 +414,7 @@ const useDeleteRequest = (deleteOptions) => {
413
414
  rej(postResponse);
414
415
  }
415
416
  };
416
- const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), { enabled: false, ...options });
417
+ const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), { enabled: false, ...options });
417
418
  const updatedPathAsync = async (link) => {
418
419
  return updateDeletePath(link);
419
420
  };
@@ -431,6 +432,67 @@ const useDeleteRequest = (deleteOptions) => {
431
432
  return { destroy, ...query };
432
433
  };
433
434
 
435
+ const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
436
+ const { API_URL, TIMEOUT } = useEnvironmentVariables();
437
+ const { getHeaders } = useQueryHeaders();
438
+ let queryClient = useQueryClient();
439
+ // eslint-disable-next-line react-hooks/exhaustive-deps
440
+ queryClient = useMemo(() => queryClient, []);
441
+ const sendRequest = async (res, rej, pageParam) => {
442
+ if (load) {
443
+ // get request headers
444
+ const globalHeaders = getHeaders();
445
+ const getResponse = await makeRequest({
446
+ path: pageParam ?? path,
447
+ headers: { ...globalHeaders, ...headers },
448
+ baseURL: baseUrl ?? API_URL,
449
+ timeout: TIMEOUT,
450
+ });
451
+ if (getResponse.status) {
452
+ res(getResponse);
453
+ }
454
+ else {
455
+ rej(getResponse);
456
+ }
457
+ }
458
+ else {
459
+ res(null);
460
+ }
461
+ };
462
+ const query = useInfiniteQuery([path, {}], ({ pageParam = path }) => new Promise((res, rej) => sendRequest(res, rej, pageParam)), {
463
+ enabled: load,
464
+ getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
465
+ getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
466
+ ...queryOptions,
467
+ });
468
+ /**
469
+ *
470
+ * This pagination implementation is currently tied to our use case
471
+ */
472
+ const constructPaginationLink = (direction, lastPage, pages) => {
473
+ const [pathname, queryString] = lastPage.split('?');
474
+ const queryParams = new URLSearchParams(queryString);
475
+ const lastPageItem = pages[pages.length - 1];
476
+ queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
477
+ return pathname + '?' + queryParams.toString();
478
+ };
479
+ useEffect(() => {
480
+ if (keyTracker) {
481
+ // set expiration time for the tracker
482
+ queryClient.setQueryDefaults([keyTracker], {
483
+ cacheTime: Infinity,
484
+ staleTime: Infinity,
485
+ });
486
+ queryClient.setQueryData([keyTracker], [path, {}]);
487
+ }
488
+ }, [keyTracker, path, queryClient, queryOptions?.staleTime]);
489
+ const flattenedData = query.data?.pages.flat() ?? [];
490
+ return {
491
+ ...query,
492
+ flattenedData,
493
+ };
494
+ };
495
+
434
496
  const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
435
497
  const [requestPath, updatePath] = useState(path);
436
498
  const [options, setOptions] = useState(queryOptions);
@@ -440,12 +502,13 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
440
502
  let queryClient = useQueryClient();
441
503
  // eslint-disable-next-line react-hooks/exhaustive-deps
442
504
  queryClient = useMemo(() => queryClient, []);
443
- const sendRequest = async (res, rej) => {
505
+ const sendRequest = async (res, rej, queryKey) => {
444
506
  if (load) {
445
507
  // get request headers
446
508
  const globalHeaders = getHeaders();
509
+ const [url] = (queryKey ?? []);
447
510
  const getResponse = await makeRequest({
448
- path: requestPath,
511
+ path: url ?? requestPath,
449
512
  headers: { ...globalHeaders, ...headers },
450
513
  baseURL: baseUrl ?? API_URL,
451
514
  timeout: TIMEOUT,
@@ -461,7 +524,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
461
524
  res(null);
462
525
  }
463
526
  };
464
- const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), {
527
+ const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), {
465
528
  enabled: load,
466
529
  ...options,
467
530
  });
@@ -624,5 +687,5 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
624
687
  return { post, ...mutation };
625
688
  };
626
689
 
627
- export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
690
+ export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetInfiniteRequest, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
628
691
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,6 @@
1
1
  export * from './queries.interface';
2
2
  export * from './useDeleteRequest';
3
+ export * from './useGetInfiniteRequest';
3
4
  export * from './useGetRequest';
4
5
  export * from './usePatchRequest';
5
6
  export * from './usePostRequest';
@@ -1,4 +1,4 @@
1
- import type { UseQueryOptions } from '@tanstack/react-query';
1
+ import type { UseInfiniteQueryOptions, UseQueryOptions } from '@tanstack/react-query';
2
2
  import type { RawAxiosRequestHeaders } from 'axios';
3
3
  import type { IRequestError, IRequestSuccess } from '../request';
4
4
  export interface IPagination {
@@ -10,6 +10,7 @@ export interface IPagination {
10
10
  total: number;
11
11
  }
12
12
  export type TanstackQueryOption<TResponse> = UseQueryOptions<IRequestSuccess<TResponse | undefined>, IRequestError, IRequestSuccess<TResponse | undefined>, Array<any>>;
13
+ export type TanstackInfiniteQueryOption<TResponse> = UseInfiniteQueryOptions<IRequestSuccess<TResponse | undefined>, IRequestError, IRequestSuccess<TResponse | undefined>, Array<any>>;
13
14
  export interface DefaultRequestOptions {
14
15
  baseUrl?: string;
15
16
  headers?: RawAxiosRequestHeaders;
@@ -13,11 +13,12 @@ const useDeleteRequest = (deleteOptions) => {
13
13
  const [options, setOptions] = useState();
14
14
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
15
15
  const { getHeaders } = useQueryHeaders();
16
- const sendRequest = async (res, rej) => {
16
+ const sendRequest = async (res, rej, queryKey) => {
17
17
  // get request headers
18
18
  const globalHeaders = getHeaders();
19
+ const [url] = (queryKey ?? []);
19
20
  const postResponse = await makeRequest({
20
- path: requestPath,
21
+ path: url ?? requestPath,
21
22
  headers: { ...globalHeaders, ...headers },
22
23
  method: HttpMethod.DELETE,
23
24
  baseURL: baseUrl ?? API_URL,
@@ -30,7 +31,7 @@ const useDeleteRequest = (deleteOptions) => {
30
31
  rej(postResponse);
31
32
  }
32
33
  };
33
- const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), { enabled: false, ...options });
34
+ const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), { enabled: false, ...options });
34
35
  const updatedPathAsync = async (link) => {
35
36
  return updateDeletePath(link);
36
37
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,140 @@
1
+ import type { IRequestSuccess } from '../request';
2
+ import type { DefaultRequestOptions, TanstackInfiniteQueryOption } from './queries.interface';
3
+ export declare const useGetInfiniteRequest: <TResponse extends Record<string, any>>({ path, load, queryOptions, keyTracker, baseUrl, headers, }: {
4
+ path: string;
5
+ load?: boolean | undefined;
6
+ queryOptions?: TanstackInfiniteQueryOption<TResponse> | undefined;
7
+ keyTracker?: string | undefined;
8
+ } & DefaultRequestOptions) => {
9
+ flattenedData: IRequestSuccess<TResponse>[];
10
+ data: undefined;
11
+ error: any;
12
+ isError: true;
13
+ isLoading: false;
14
+ isLoadingError: true;
15
+ isRefetchError: false;
16
+ isSuccess: false;
17
+ status: "error";
18
+ fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
19
+ fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
20
+ hasNextPage?: boolean | undefined;
21
+ hasPreviousPage?: boolean | undefined;
22
+ isFetchingNextPage: boolean;
23
+ isFetchingPreviousPage: boolean;
24
+ dataUpdatedAt: number;
25
+ errorUpdatedAt: number;
26
+ failureCount: number;
27
+ failureReason: any;
28
+ errorUpdateCount: number;
29
+ isFetched: boolean;
30
+ isFetchedAfterMount: boolean;
31
+ isFetching: boolean;
32
+ isInitialLoading: boolean;
33
+ isPaused: boolean;
34
+ isPlaceholderData: boolean;
35
+ isPreviousData: boolean;
36
+ isRefetching: boolean;
37
+ isStale: boolean;
38
+ refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
39
+ remove: () => void;
40
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
41
+ } | {
42
+ flattenedData: IRequestSuccess<TResponse>[];
43
+ data: undefined;
44
+ error: null;
45
+ isError: false;
46
+ isLoading: true;
47
+ isLoadingError: false;
48
+ isRefetchError: false;
49
+ isSuccess: false;
50
+ status: "loading";
51
+ fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
52
+ fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
53
+ hasNextPage?: boolean | undefined;
54
+ hasPreviousPage?: boolean | undefined;
55
+ isFetchingNextPage: boolean;
56
+ isFetchingPreviousPage: boolean;
57
+ dataUpdatedAt: number;
58
+ errorUpdatedAt: number;
59
+ failureCount: number;
60
+ failureReason: any;
61
+ errorUpdateCount: number;
62
+ isFetched: boolean;
63
+ isFetchedAfterMount: boolean;
64
+ isFetching: boolean;
65
+ isInitialLoading: boolean;
66
+ isPaused: boolean;
67
+ isPlaceholderData: boolean;
68
+ isPreviousData: boolean;
69
+ isRefetching: boolean;
70
+ isStale: boolean;
71
+ refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
72
+ remove: () => void;
73
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
74
+ } | {
75
+ flattenedData: IRequestSuccess<TResponse>[];
76
+ data: import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>;
77
+ error: any;
78
+ isError: true;
79
+ isLoading: false;
80
+ isLoadingError: false;
81
+ isRefetchError: true;
82
+ isSuccess: false;
83
+ status: "error";
84
+ fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
85
+ fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
86
+ hasNextPage?: boolean | undefined;
87
+ hasPreviousPage?: boolean | undefined;
88
+ isFetchingNextPage: boolean;
89
+ isFetchingPreviousPage: boolean;
90
+ dataUpdatedAt: number;
91
+ errorUpdatedAt: number;
92
+ failureCount: number;
93
+ failureReason: any;
94
+ errorUpdateCount: number;
95
+ isFetched: boolean;
96
+ isFetchedAfterMount: boolean;
97
+ isFetching: boolean;
98
+ isInitialLoading: boolean;
99
+ isPaused: boolean;
100
+ isPlaceholderData: boolean;
101
+ isPreviousData: boolean;
102
+ isRefetching: boolean;
103
+ isStale: boolean;
104
+ refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
105
+ remove: () => void;
106
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
107
+ } | {
108
+ flattenedData: IRequestSuccess<TResponse>[];
109
+ data: import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>;
110
+ error: null;
111
+ isError: false;
112
+ isLoading: false;
113
+ isLoadingError: false;
114
+ isRefetchError: false;
115
+ isSuccess: true;
116
+ status: "success";
117
+ fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
118
+ fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
119
+ hasNextPage?: boolean | undefined;
120
+ hasPreviousPage?: boolean | undefined;
121
+ isFetchingNextPage: boolean;
122
+ isFetchingPreviousPage: boolean;
123
+ dataUpdatedAt: number;
124
+ errorUpdatedAt: number;
125
+ failureCount: number;
126
+ failureReason: any;
127
+ errorUpdateCount: number;
128
+ isFetched: boolean;
129
+ isFetchedAfterMount: boolean;
130
+ isFetching: boolean;
131
+ isInitialLoading: boolean;
132
+ isPaused: boolean;
133
+ isPlaceholderData: boolean;
134
+ isPreviousData: boolean;
135
+ isRefetching: boolean;
136
+ isStale: boolean;
137
+ refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
138
+ remove: () => void;
139
+ fetchStatus: import("@tanstack/react-query").FetchStatus;
140
+ };
@@ -0,0 +1,72 @@
1
+ import { useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
2
+ import { useMemo, useEffect } from 'react';
3
+ import 'url-search-params-polyfill';
4
+ import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
5
+ import { useQueryHeaders } from '../config/useQueryHeaders.js';
6
+ import 'axios';
7
+ import { makeRequest } from '../request/make-request.js';
8
+ import '../request/request.enum.js';
9
+
10
+ const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
11
+ const { API_URL, TIMEOUT } = useEnvironmentVariables();
12
+ const { getHeaders } = useQueryHeaders();
13
+ let queryClient = useQueryClient();
14
+ // eslint-disable-next-line react-hooks/exhaustive-deps
15
+ queryClient = useMemo(() => queryClient, []);
16
+ const sendRequest = async (res, rej, pageParam) => {
17
+ if (load) {
18
+ // get request headers
19
+ const globalHeaders = getHeaders();
20
+ const getResponse = await makeRequest({
21
+ path: pageParam ?? path,
22
+ headers: { ...globalHeaders, ...headers },
23
+ baseURL: baseUrl ?? API_URL,
24
+ timeout: TIMEOUT,
25
+ });
26
+ if (getResponse.status) {
27
+ res(getResponse);
28
+ }
29
+ else {
30
+ rej(getResponse);
31
+ }
32
+ }
33
+ else {
34
+ res(null);
35
+ }
36
+ };
37
+ const query = useInfiniteQuery([path, {}], ({ pageParam = path }) => new Promise((res, rej) => sendRequest(res, rej, pageParam)), {
38
+ enabled: load,
39
+ getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
40
+ getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
41
+ ...queryOptions,
42
+ });
43
+ /**
44
+ *
45
+ * This pagination implementation is currently tied to our use case
46
+ */
47
+ const constructPaginationLink = (direction, lastPage, pages) => {
48
+ const [pathname, queryString] = lastPage.split('?');
49
+ const queryParams = new URLSearchParams(queryString);
50
+ const lastPageItem = pages[pages.length - 1];
51
+ queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
52
+ return pathname + '?' + queryParams.toString();
53
+ };
54
+ useEffect(() => {
55
+ if (keyTracker) {
56
+ // set expiration time for the tracker
57
+ queryClient.setQueryDefaults([keyTracker], {
58
+ cacheTime: Infinity,
59
+ staleTime: Infinity,
60
+ });
61
+ queryClient.setQueryData([keyTracker], [path, {}]);
62
+ }
63
+ }, [keyTracker, path, queryClient, queryOptions?.staleTime]);
64
+ const flattenedData = query.data?.pages.flat() ?? [];
65
+ return {
66
+ ...query,
67
+ flattenedData,
68
+ };
69
+ };
70
+
71
+ export { useGetInfiniteRequest };
72
+ //# sourceMappingURL=useGetInfiniteRequest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGetInfiniteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -16,12 +16,13 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
16
16
  let queryClient = useQueryClient();
17
17
  // eslint-disable-next-line react-hooks/exhaustive-deps
18
18
  queryClient = useMemo(() => queryClient, []);
19
- const sendRequest = async (res, rej) => {
19
+ const sendRequest = async (res, rej, queryKey) => {
20
20
  if (load) {
21
21
  // get request headers
22
22
  const globalHeaders = getHeaders();
23
+ const [url] = (queryKey ?? []);
23
24
  const getResponse = await makeRequest({
24
- path: requestPath,
25
+ path: url ?? requestPath,
25
26
  headers: { ...globalHeaders, ...headers },
26
27
  baseURL: baseUrl ?? API_URL,
27
28
  timeout: TIMEOUT,
@@ -37,7 +38,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
37
38
  res(null);
38
39
  }
39
40
  };
40
- const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), {
41
+ const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), {
41
42
  enabled: load,
42
43
  ...options,
43
44
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ventlio/tanstack-query",
3
- "version": "0.2.73",
3
+ "version": "0.2.74",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "contributors": [
@@ -1,5 +1,6 @@
1
1
  export * from './queries.interface';
2
2
  export * from './useDeleteRequest';
3
+ export * from './useGetInfiniteRequest';
3
4
  export * from './useGetRequest';
4
5
  export * from './usePatchRequest';
5
6
  export * from './usePostRequest';
@@ -1,4 +1,4 @@
1
- import type { UseQueryOptions } from '@tanstack/react-query';
1
+ import type { UseInfiniteQueryOptions, UseQueryOptions } from '@tanstack/react-query';
2
2
  import type { RawAxiosRequestHeaders } from 'axios';
3
3
  import type { IRequestError, IRequestSuccess } from '../request';
4
4
 
@@ -18,6 +18,13 @@ export type TanstackQueryOption<TResponse> = UseQueryOptions<
18
18
  Array<any>
19
19
  >;
20
20
 
21
+ export type TanstackInfiniteQueryOption<TResponse> = UseInfiniteQueryOptions<
22
+ IRequestSuccess<TResponse | undefined>,
23
+ IRequestError,
24
+ IRequestSuccess<TResponse | undefined>,
25
+ Array<any>
26
+ >;
27
+
21
28
  export interface DefaultRequestOptions {
22
29
  baseUrl?: string;
23
30
  headers?: RawAxiosRequestHeaders;
@@ -1,4 +1,4 @@
1
- import type { UseQueryOptions } from '@tanstack/react-query';
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
4
  import { useState } from 'react';
@@ -16,12 +16,14 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
16
16
 
17
17
  const { getHeaders } = useQueryHeaders();
18
18
 
19
- const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void) => {
19
+ const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void, queryKey?: QueryKey) => {
20
20
  // get request headers
21
21
  const globalHeaders: RawAxiosRequestHeaders = getHeaders();
22
22
 
23
+ const [url] = (queryKey ?? []) as string[];
24
+
23
25
  const postResponse = await makeRequest<TResponse>({
24
- path: requestPath,
26
+ path: url ?? requestPath,
25
27
  headers: { ...globalHeaders, ...headers },
26
28
  method: HttpMethod.DELETE,
27
29
  baseURL: baseUrl ?? API_URL,
@@ -37,7 +39,8 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
37
39
 
38
40
  const query = useQuery<any, any, IRequestSuccess<TResponse>>(
39
41
  [requestPath, {}],
40
- () => new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej)),
42
+ ({ queryKey }) =>
43
+ new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
41
44
  { enabled: false, ...options }
42
45
  );
43
46
 
@@ -0,0 +1,121 @@
1
+ import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
2
+ import type { RawAxiosRequestHeaders } from 'axios';
3
+ import { useEffect, useMemo } from 'react';
4
+ import { useEnvironmentVariables, useQueryHeaders } from '../config';
5
+
6
+ import type { IRequestError, IRequestSuccess } from '../request';
7
+ import { makeRequest } from '../request';
8
+ import type { DefaultRequestOptions, TanstackInfiniteQueryOption } from './queries.interface';
9
+
10
+ interface Pagination {
11
+ previous_page: number;
12
+ current_page: number;
13
+ next_page: number;
14
+ size: number;
15
+ page_count: number;
16
+ total: number;
17
+ }
18
+
19
+ export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
20
+ path,
21
+ load = false,
22
+ queryOptions,
23
+ keyTracker,
24
+ baseUrl,
25
+ headers,
26
+ }: {
27
+ path: string;
28
+ load?: boolean;
29
+ queryOptions?: TanstackInfiniteQueryOption<TResponse>;
30
+ keyTracker?: string;
31
+ } & DefaultRequestOptions) => {
32
+ const { API_URL, TIMEOUT } = useEnvironmentVariables();
33
+ const { getHeaders } = useQueryHeaders();
34
+
35
+ let queryClient = useQueryClient();
36
+
37
+ // eslint-disable-next-line react-hooks/exhaustive-deps
38
+ queryClient = useMemo(() => queryClient, []);
39
+
40
+ const sendRequest = async (
41
+ res: (
42
+ value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
43
+ ) => void,
44
+ rej: (reason?: any) => void,
45
+ pageParam?: string
46
+ ) => {
47
+ if (load) {
48
+ // get request headers
49
+ const globalHeaders: RawAxiosRequestHeaders = getHeaders();
50
+
51
+ const getResponse = await makeRequest<TResponse>({
52
+ path: pageParam ?? path,
53
+ headers: { ...globalHeaders, ...headers },
54
+ baseURL: baseUrl ?? API_URL,
55
+ timeout: TIMEOUT,
56
+ });
57
+
58
+ if (getResponse.status) {
59
+ res(getResponse as IRequestSuccess<TResponse>);
60
+ } else {
61
+ rej(getResponse);
62
+ }
63
+ } else {
64
+ res(null as any);
65
+ }
66
+ };
67
+
68
+ const query = useInfiniteQuery<any, any, IRequestSuccess<TResponse>>(
69
+ [path, {}],
70
+ ({ pageParam = path }) =>
71
+ new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, pageParam)),
72
+ {
73
+ enabled: load,
74
+ getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
75
+ getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
76
+ ...(queryOptions as any),
77
+ }
78
+ );
79
+
80
+ /**
81
+ *
82
+ * This pagination implementation is currently tied to our use case
83
+ */
84
+ const constructPaginationLink = (
85
+ direction: 'next_page' | 'previous_page',
86
+ lastPage: string,
87
+ pages: IRequestSuccess<
88
+ TResponse & {
89
+ pagination: Pagination;
90
+ }
91
+ >[]
92
+ ) => {
93
+ const [pathname, queryString] = lastPage.split('?');
94
+
95
+ const queryParams = new URLSearchParams(queryString);
96
+ const lastPageItem = pages[pages.length - 1];
97
+
98
+ queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
99
+
100
+ return pathname + '?' + queryParams.toString();
101
+ };
102
+
103
+ useEffect(() => {
104
+ if (keyTracker) {
105
+ // set expiration time for the tracker
106
+ queryClient.setQueryDefaults([keyTracker], {
107
+ cacheTime: Infinity,
108
+ staleTime: Infinity,
109
+ });
110
+
111
+ queryClient.setQueryData([keyTracker], [path, {}]);
112
+ }
113
+ }, [keyTracker, path, queryClient, queryOptions?.staleTime]);
114
+
115
+ const flattenedData = query.data?.pages.flat() ?? [];
116
+
117
+ return {
118
+ ...query,
119
+ flattenedData,
120
+ };
121
+ };
@@ -1,4 +1,4 @@
1
- import type { UseQueryOptions } from '@tanstack/react-query';
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
4
  import type { RawAxiosRequestHeaders } from '../../node_modules/axios/index';
@@ -37,14 +37,17 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
37
37
  res: (
38
38
  value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
39
39
  ) => void,
40
- rej: (reason?: any) => void
40
+ rej: (reason?: any) => void,
41
+ queryKey?: QueryKey
41
42
  ) => {
42
43
  if (load) {
43
44
  // get request headers
44
45
  const globalHeaders: RawAxiosRequestHeaders = getHeaders();
45
46
 
47
+ const [url] = (queryKey ?? []) as string[];
48
+
46
49
  const getResponse = await makeRequest<TResponse>({
47
- path: requestPath,
50
+ path: url ?? requestPath,
48
51
  headers: { ...globalHeaders, ...headers },
49
52
  baseURL: baseUrl ?? API_URL,
50
53
  timeout: TIMEOUT,
@@ -62,7 +65,8 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
62
65
 
63
66
  const query = useQuery<any, any, IRequestSuccess<TResponse>>(
64
67
  [requestPath, {}],
65
- () => new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej)),
68
+ ({ queryKey }) =>
69
+ new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
66
70
  {
67
71
  enabled: load,
68
72
  ...options,