@ventlio/tanstack-query 0.5.12 → 0.5.14

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 (63) hide show
  1. package/dist/config/bootstrapQueryRequest.d.ts +6 -0
  2. package/dist/config/useEnvironmentVariables.d.ts +4 -0
  3. package/dist/helpers/index.d.ts +1 -0
  4. package/dist/helpers/result.d.ts +23 -0
  5. package/dist/index.mjs +368 -95
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/node_modules/@tanstack/react-store/dist/esm/index.js +1 -1
  8. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim/with-selector.development.js +1 -1
  9. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js.map +1 -0
  10. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim/with-selector.production.js +1 -1
  11. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js.map +1 -0
  12. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim.development.js +1 -1
  13. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +1 -0
  14. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim.production.js +1 -1
  15. package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +1 -0
  16. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/index.js +1 -1
  17. package/dist/node_modules/use-sync-external-store/shim/index.js.map +1 -0
  18. package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/with-selector.js +1 -1
  19. package/dist/node_modules/use-sync-external-store/shim/with-selector.js.map +1 -0
  20. package/dist/queries/useGetRequest.d.ts +12 -2
  21. package/dist/request/make-request.d.ts +12 -1
  22. package/dist/src/config/bootstrapQueryRequest.js +41 -1
  23. package/dist/src/config/bootstrapQueryRequest.js.map +1 -1
  24. package/dist/src/config/useEnvironmentVariables.js +35 -4
  25. package/dist/src/config/useEnvironmentVariables.js.map +1 -1
  26. package/dist/src/helpers/result.js +59 -0
  27. package/dist/src/helpers/result.js.map +1 -0
  28. package/dist/src/index.js +2 -1
  29. package/dist/src/index.js.map +1 -1
  30. package/dist/src/model/useQueryModel.js +1 -1
  31. package/dist/src/queries/useDeleteRequest.js +19 -14
  32. package/dist/src/queries/useDeleteRequest.js.map +1 -1
  33. package/dist/src/queries/useGetInfiniteRequest.js +17 -12
  34. package/dist/src/queries/useGetInfiniteRequest.js.map +1 -1
  35. package/dist/src/queries/useGetRequest.js +86 -28
  36. package/dist/src/queries/useGetRequest.js.map +1 -1
  37. package/dist/src/queries/usePatchRequest.js +19 -14
  38. package/dist/src/queries/usePatchRequest.js.map +1 -1
  39. package/dist/src/queries/usePostRequest.js +18 -13
  40. package/dist/src/queries/usePostRequest.js.map +1 -1
  41. package/dist/src/request/make-request.js +75 -6
  42. package/dist/src/request/make-request.js.map +1 -1
  43. package/dist/types/index.d.ts +24 -5
  44. package/package.json +2 -4
  45. package/src/config/bootstrapQueryRequest.ts +47 -2
  46. package/src/config/useEnvironmentVariables.ts +42 -4
  47. package/src/helpers/index.ts +1 -0
  48. package/src/helpers/result.ts +65 -0
  49. package/src/model/useQueryModel.ts +2 -2
  50. package/src/queries/useDeleteRequest.ts +18 -20
  51. package/src/queries/useGetInfiniteRequest.ts +17 -17
  52. package/src/queries/useGetRequest.ts +109 -33
  53. package/src/queries/usePatchRequest.ts +19 -16
  54. package/src/queries/usePostRequest.ts +18 -15
  55. package/src/queries/usePutRequest.ts +16 -15
  56. package/src/request/make-request.ts +112 -15
  57. package/src/types/index.ts +38 -4
  58. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js.map +0 -1
  59. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js.map +0 -1
  60. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +0 -1
  61. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +0 -1
  62. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/shim/index.js.map +0 -1
  63. package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/shim/with-selector.js.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,8 +1,7 @@
1
1
  import 'url-search-params-polyfill';
2
- import { create } from 'zustand';
3
2
  import require$$0, { useState, useEffect, useMemo, startTransition } from 'react';
3
+ import { create } from 'zustand';
4
4
  import { useQueryClient, useQuery, useInfiniteQuery, useMutation } from '@tanstack/react-query';
5
- import result from 'lodash.result';
6
5
  import lodashSet from 'lodash.set';
7
6
  import axios from 'axios';
8
7
 
@@ -700,17 +699,52 @@ const bootStore = new Store({
700
699
  modelConfig: undefined,
701
700
  });
702
701
 
702
+ /**
703
+ * Bootstrap the query request system with configuration options
704
+ *
705
+ * @param queryClient - TanStack Query client instance
706
+ * @param options - Configuration options
707
+ */
703
708
  const bootstrapQueryRequest = async (queryClient, options = {}) => {
704
- // set default query config
709
+ // Resume any paused mutations
705
710
  await queryClient.resumePausedMutations();
711
+ // Set default pagination configuration if not provided
712
+ if (!options.pagination) {
713
+ options.pagination = {
714
+ pageParamName: 'page',
715
+ buildPaginationUrl: (url, page) => {
716
+ const [pathname, queryString] = url.split('?');
717
+ const queryParams = new URLSearchParams(queryString);
718
+ queryParams.set('page', String(page));
719
+ return pathname + '?' + queryParams.toString();
720
+ },
721
+ extractPagination: (response) => {
722
+ // Default pagination extraction from response
723
+ if (response.data && 'pagination' in response.data) {
724
+ return response.data.pagination;
725
+ }
726
+ return undefined;
727
+ },
728
+ };
729
+ }
730
+ // Convert legacy middleware to new format if needed
731
+ if (options.middleware && !Array.isArray(options.middleware)) {
732
+ const legacyMiddleware = options.middleware;
733
+ // Create a new middleware function that adapts the legacy format
734
+ const adaptedMiddleware = async (context, next) => {
735
+ return await legacyMiddleware((opts) => next(opts), {
736
+ baseUrl: context.baseUrl,
737
+ path: context.path,
738
+ body: context.body,
739
+ });
740
+ };
741
+ // Replace with array containing the adapted middleware
742
+ options.middleware = [adaptedMiddleware];
743
+ }
744
+ // Store the configuration
706
745
  bootStore.setState(() => options);
707
746
  };
708
747
 
709
- const useBaseUrlStore = create((set) => ({
710
- baseUrl: undefined,
711
- setBaseUrl: (baseUrl) => set({ baseUrl }),
712
- }));
713
-
714
748
  const useReactNativeEnv = () => {
715
749
  const { environments, context } = useStore(bootStore);
716
750
  const appUrl = environments?.appBaseUrl;
@@ -719,14 +753,48 @@ const useReactNativeEnv = () => {
719
753
  return { appUrl, appTimeout, isApp };
720
754
  };
721
755
 
756
+ const useBaseUrlStore = create((set) => ({
757
+ baseUrl: undefined,
758
+ setBaseUrl: (baseUrl) => set({ baseUrl }),
759
+ }));
760
+
761
+ /**
762
+ * Hook to access environment variables across different frameworks
763
+ * Supports React (CRA), Next.js, Vite, and React Native
764
+ */
722
765
  const useEnvironmentVariables = () => {
723
766
  const { appTimeout, appUrl } = useReactNativeEnv();
724
767
  const { baseUrl } = useBaseUrlStore();
725
- const url = baseUrl ?? process.env.REACT_APP_API_URL ?? process.env.NEXT_PUBLIC_API_URL ?? appUrl;
726
- const timeout = baseUrl ?? process.env.REACT_APP_API_TIMEOUT ?? process.env.NEXT_PUBLIC_API_TIMEOUT ?? appTimeout;
768
+ const { environments } = useStore(bootStore);
769
+ // Framework environment variables detection
770
+ // Order of precedence:
771
+ // 1. Runtime baseUrl (set via useBaseUrlStore)
772
+ // 2. Bootstrap config environments
773
+ // 3. Framework-specific environment variables
774
+ // 4. React Native app URL
775
+ // Get global object to check for various environment variables
776
+ const globalObj = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {};
777
+ // Check for Vite environment variables (without using import.meta directly)
778
+ // @ts-ignore - Access potential Vite environment variables
779
+ const viteEnv = globalObj.__VITE_ENV__ || {};
780
+ const viteApiUrl = viteEnv.VITE_API_URL;
781
+ const viteApiTimeout = viteEnv.VITE_API_TIMEOUT;
782
+ // Get URL with fallbacks
783
+ const url = baseUrl ??
784
+ environments?.appBaseUrl ??
785
+ process.env.REACT_APP_API_URL ??
786
+ process.env.NEXT_PUBLIC_API_URL ??
787
+ viteApiUrl ??
788
+ appUrl;
789
+ // Get timeout with fallbacks
790
+ const timeout = environments?.appTimeout ??
791
+ process.env.REACT_APP_API_TIMEOUT ??
792
+ process.env.NEXT_PUBLIC_API_TIMEOUT ??
793
+ viteApiTimeout ??
794
+ appTimeout;
727
795
  return {
728
796
  API_URL: url,
729
- TIMEOUT: Number(timeout),
797
+ TIMEOUT: Number(timeout) || 30000, // Default timeout of 30 seconds
730
798
  };
731
799
  };
732
800
 
@@ -763,6 +831,63 @@ const useQueryHeaders = () => {
763
831
  return { setQueryHeaders, getHeaders };
764
832
  };
765
833
 
834
+ /**
835
+ * Gets the value at path of object. If the resolved value is a function,
836
+ * it's invoked with the this binding of its parent object and its result is returned.
837
+ * Similar to lodash.result functionality.
838
+ *
839
+ * @param object - The object to query
840
+ * @param path - The path of the property to get (supports dot notation)
841
+ * @param defaultValue - The value returned if the resolved value is undefined
842
+ * @returns The resolved value
843
+ *
844
+ * @example
845
+ * const obj = { a: { b: { c: 'value' } } };
846
+ * result(obj, 'a.b.c'); // => 'value'
847
+ *
848
+ * @example
849
+ * const obj = { a: { b: () => 'computed' } };
850
+ * result(obj, 'a.b'); // => 'computed'
851
+ *
852
+ * @example
853
+ * result({}, 'a.b.c', 'default'); // => 'default'
854
+ */
855
+ function result(object, path, defaultValue) {
856
+ if (object == null) {
857
+ return defaultValue;
858
+ }
859
+ // Convert path to array if it's a string
860
+ const pathArray = Array.isArray(path)
861
+ ? path
862
+ : path
863
+ .split('.')
864
+ .flatMap((part) => part.split('[').flatMap((p) => p.split(']')))
865
+ .filter(Boolean);
866
+ let current = object;
867
+ let parent = object;
868
+ // Traverse the path
869
+ for (let i = 0; i < pathArray.length; i++) {
870
+ if (current == null) {
871
+ return defaultValue;
872
+ }
873
+ parent = current;
874
+ const key = pathArray[i];
875
+ if (key === undefined) {
876
+ return defaultValue;
877
+ }
878
+ current = current[key];
879
+ }
880
+ // If the final value is undefined, return the default value
881
+ if (current === undefined) {
882
+ return defaultValue;
883
+ }
884
+ // If the value is a function, invoke it with the parent object as context
885
+ if (typeof current === 'function') {
886
+ return current.call(parent);
887
+ }
888
+ return current;
889
+ }
890
+
766
891
  const scrollToTop = () => {
767
892
  window.scrollTo({
768
893
  top: 0,
@@ -1017,23 +1142,92 @@ const successTransformer = (data) => {
1017
1142
  };
1018
1143
  };
1019
1144
 
1020
- async function makeRequest({ body = {}, method = HttpMethod.GET, path, isFormData, headers = {}, baseURL, timeout, appFileConfig, onUploadProgress, }) {
1145
+ /**
1146
+ * Execute a chain of middleware functions
1147
+ */
1148
+ async function executeMiddlewareChain(middlewares, context, finalHandler) {
1149
+ // Create a chain of middleware functions
1150
+ const chain = middlewares.reduceRight((next, middleware) => {
1151
+ return (options) => {
1152
+ // Update context with new options if provided
1153
+ const updatedContext = options ? { ...context, options: { ...context.options, ...options } } : context;
1154
+ return middleware(updatedContext, next);
1155
+ };
1156
+ }, finalHandler);
1157
+ // Execute the middleware chain
1158
+ return await chain(undefined);
1159
+ }
1160
+ /**
1161
+ * Make an HTTP request with middleware support
1162
+ *
1163
+ * @param requestOptions - Request options
1164
+ * @param middlewares - Optional array of middleware functions
1165
+ */
1166
+ async function makeRequest(requestOptions, middlewares) {
1167
+ const { body = {}, method = HttpMethod.GET, path, isFormData, headers = {}, baseURL, timeout, appFileConfig, onUploadProgress, } = requestOptions;
1021
1168
  // check if file is included in mobile app environment and extract all file input to avoid
1022
1169
  // it being formatted to object using axios formData builder
1023
1170
  const isApp = appFileConfig?.isApp;
1024
1171
  const appFiles = isApp ? getAppFiles(body, appFileConfig.fileSelectors) : {};
1025
1172
  // configure body
1026
- body = (isFormData ? axios.toFormData(body) : body);
1027
- // configure request header1
1028
- configureRequestHeader(isFormData, headers, isApp, appFiles, body);
1173
+ const processedBody = (isFormData ? axios.toFormData(body) : body);
1174
+ // configure request header
1175
+ configureRequestHeader(isFormData, headers, isApp, appFiles, processedBody);
1176
+ // Create the final handler that makes the actual request
1177
+ const finalHandler = async (options) => {
1178
+ const finalRequestOptions = options
1179
+ ? {
1180
+ ...requestOptions,
1181
+ body: processedBody,
1182
+ ...options,
1183
+ }
1184
+ : {
1185
+ ...requestOptions,
1186
+ body: processedBody,
1187
+ };
1188
+ return await performRequest(finalRequestOptions);
1189
+ };
1190
+ // If middleware is available, execute the middleware chain
1191
+ if (middlewares && middlewares.length > 0) {
1192
+ const context = {
1193
+ baseUrl: baseURL,
1194
+ path,
1195
+ body: body,
1196
+ method,
1197
+ headers,
1198
+ options: {
1199
+ baseURL,
1200
+ timeout,
1201
+ path,
1202
+ body: processedBody,
1203
+ method,
1204
+ isFormData,
1205
+ headers,
1206
+ appFileConfig,
1207
+ onUploadProgress,
1208
+ },
1209
+ };
1210
+ return await executeMiddlewareChain(middlewares, context, finalHandler);
1211
+ }
1212
+ // Otherwise, just make the request directly
1213
+ return await finalHandler(undefined);
1214
+ }
1215
+ /**
1216
+ * Perform the actual HTTP request
1217
+ */
1218
+ async function performRequest({ body, method, path, isFormData, headers, baseURL, timeout, appFileConfig, onUploadProgress, }) {
1029
1219
  try {
1030
1220
  const axiosRequest = axiosInstance({ baseURL, headers, timeout });
1221
+ const isApp = appFileConfig?.isApp;
1031
1222
  const axiosRequestConfig = {
1032
1223
  url: path,
1033
1224
  method,
1034
1225
  onUploadProgress,
1035
1226
  };
1036
- if (Object.keys(body).length > 0 || (isFormData && !isApp && [...body.keys()].length > 0)) {
1227
+ // Check if body exists and is not null
1228
+ if (body &&
1229
+ ((typeof body === 'object' && Object.keys(body).length > 0) ||
1230
+ (isFormData && !isApp && body instanceof FormData && Array.from(body.keys()).length > 0))) {
1037
1231
  axiosRequestConfig.data = body;
1038
1232
  }
1039
1233
  // send request
@@ -1103,7 +1297,8 @@ const useDeleteRequest = (deleteOptions) => {
1103
1297
  const { baseUrl, headers } = deleteOptions ?? {};
1104
1298
  const [requestPath, setRequestPath] = useState('');
1105
1299
  const [options, setOptions] = useState();
1106
- const { middleware } = useStore(bootStore);
1300
+ // const { middleware: middlewares } = useStore(bootStore);
1301
+ // const [middleware] = middlewares as unknown as MiddlewareFunction[];
1107
1302
  const [requestPayload, setRequestPayload] = useState();
1108
1303
  const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
1109
1304
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
@@ -1118,17 +1313,22 @@ const useDeleteRequest = (deleteOptions) => {
1118
1313
  method: HttpMethod.DELETE,
1119
1314
  timeout: TIMEOUT,
1120
1315
  };
1121
- let deleteResponse;
1122
- if (middleware) {
1123
- // perform global middleware
1124
- deleteResponse = await middleware(async (middlewareOptions) => await makeRequest(middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions), {
1125
- path: requestUrl,
1126
- baseUrl: baseUrl ?? API_URL,
1127
- });
1128
- }
1129
- else {
1130
- deleteResponse = await makeRequest(requestOptions);
1131
- }
1316
+ // let deleteResponse: IRequestError | IRequestSuccess<TResponse>;
1317
+ // if (middleware) {
1318
+ // // perform global middleware
1319
+ // deleteResponse = await middleware(
1320
+ // async (middlewareOptions) =>
1321
+ // await makeRequest<TResponse>(
1322
+ // middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions
1323
+ // ),
1324
+ // {
1325
+ // path: requestUrl,
1326
+ // baseUrl: baseUrl ?? API_URL,
1327
+ // }
1328
+ // );
1329
+ // } else {
1330
+ const deleteResponse = await makeRequest(requestOptions);
1331
+ // }
1132
1332
  if (deleteResponse.status) {
1133
1333
  res(deleteResponse);
1134
1334
  }
@@ -1178,7 +1378,7 @@ const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, b
1178
1378
  const globalHeaders = useHeaderStore((state) => state.headers);
1179
1379
  const [requestPath, setRequestPath] = useState(path);
1180
1380
  const [options, setOptions] = useState(queryOptions);
1181
- const { middleware } = useStore(bootStore);
1381
+ useStore(bootStore);
1182
1382
  const [requestPayload, setRequestPayload] = useState();
1183
1383
  const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
1184
1384
  let queryClient = useQueryClient();
@@ -1193,17 +1393,22 @@ const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, b
1193
1393
  baseURL: baseUrl ?? API_URL,
1194
1394
  timeout: TIMEOUT,
1195
1395
  };
1196
- let getResponse;
1197
- if (middleware) {
1198
- // perform global middleware
1199
- getResponse = await middleware(async (middlewareOptions) => await makeRequest(middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions), {
1200
- path,
1201
- baseUrl: baseUrl ?? API_URL,
1202
- });
1203
- }
1204
- else {
1205
- getResponse = await makeRequest(requestOptions);
1206
- }
1396
+ // let getResponse: IRequestError | IRequestSuccess<TResponse>;
1397
+ // if (middleware) {
1398
+ // // perform global middleware
1399
+ // getResponse = await middleware(
1400
+ // async (middlewareOptions) =>
1401
+ // await makeRequest<TResponse>(
1402
+ // middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions
1403
+ // ),
1404
+ // {
1405
+ // path,
1406
+ // baseUrl: baseUrl ?? API_URL,
1407
+ // }
1408
+ // );
1409
+ // } else {
1410
+ const getResponse = await makeRequest(requestOptions);
1411
+ // }
1207
1412
  if (getResponse.status) {
1208
1413
  res(getResponse);
1209
1414
  }
@@ -1278,18 +1483,26 @@ const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, b
1278
1483
  };
1279
1484
  };
1280
1485
 
1281
- const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
1486
+ /**
1487
+ * Hook for making GET requests with pagination support
1488
+ */
1489
+ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, paginationConfig, }) => {
1282
1490
  const [requestPath, setRequestPath] = useState(path);
1283
1491
  const [options, setOptions] = useState(queryOptions);
1284
1492
  const [page, setPage] = useState(1);
1285
1493
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
1286
- const { middleware } = useStore(bootStore);
1494
+ const { middleware, pagination: globalPaginationConfig } = useStore(bootStore);
1287
1495
  const globalHeaders = useHeaderStore((state) => state.headers);
1288
1496
  const [requestPayload, setRequestPayload] = useState();
1289
1497
  const isFutureQueriesPaused = usePauseFutureRequests((state) => state.isFutureQueriesPaused);
1290
1498
  let queryClient = useQueryClient();
1291
1499
  // eslint-disable-next-line react-hooks/exhaustive-deps
1292
1500
  queryClient = useMemo(() => queryClient, []);
1501
+ // Merge global and local pagination config
1502
+ const pagination = useMemo(() => ({
1503
+ ...globalPaginationConfig,
1504
+ ...paginationConfig,
1505
+ }), [globalPaginationConfig, paginationConfig]);
1293
1506
  const sendRequest = async (res, rej, queryKey) => {
1294
1507
  const [url] = queryKey;
1295
1508
  const requestUrl = (url ?? requestPath);
@@ -1299,15 +1512,23 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
1299
1512
  baseURL: baseUrl ?? API_URL,
1300
1513
  timeout: TIMEOUT,
1301
1514
  };
1515
+ // Create the final handler that makes the actual request
1516
+ const finalHandler = async (options) => {
1517
+ const finalOptions = options ? { ...requestOptions, ...options } : requestOptions;
1518
+ return await makeRequest(finalOptions);
1519
+ };
1302
1520
  let getResponse;
1303
- if (middleware) {
1304
- // perform global middleware
1305
- getResponse = await middleware(async (middlewareOptions) => await makeRequest(middlewareOptions ? { ...requestOptions, ...middlewareOptions } : requestOptions), {
1306
- path,
1521
+ // If middleware is available, execute the middleware chain
1522
+ if (middleware && Array.isArray(middleware) && middleware.length > 0) {
1523
+ const context = {
1307
1524
  baseUrl: baseUrl ?? API_URL,
1308
- });
1525
+ path: requestUrl,
1526
+ options: requestOptions,
1527
+ };
1528
+ getResponse = await executeMiddlewareChain(middleware, context, finalHandler);
1309
1529
  }
1310
1530
  else {
1531
+ // Otherwise, just make the request directly
1311
1532
  getResponse = await makeRequest(requestOptions);
1312
1533
  }
1313
1534
  if (getResponse.status) {
@@ -1337,34 +1558,72 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
1337
1558
  queryClient.setQueryData([keyTracker], [requestPath, {}]);
1338
1559
  }
1339
1560
  }, [keyTracker, requestPath, queryClient, queryOptions?.staleTime]);
1561
+ /**
1562
+ * Extract pagination data from response using configured extractor
1563
+ */
1564
+ const getPaginationData = (response) => {
1565
+ // Use the configured pagination extractor or fall back to default
1566
+ const extractPagination = pagination.extractPagination ||
1567
+ ((res) => {
1568
+ if ('pagination' in res.data) {
1569
+ return res.data.pagination;
1570
+ }
1571
+ return undefined;
1572
+ });
1573
+ return extractPagination(response);
1574
+ };
1575
+ /**
1576
+ * Navigate to the next page if available
1577
+ */
1340
1578
  const nextPage = () => {
1341
- if (query.data.data.pagination) {
1342
- const pagination = query.data.data.pagination;
1343
- if (pagination.next_page !== pagination.current_page && pagination.next_page > pagination.current_page) {
1344
- setRequestPath(constructPaginationLink(requestPath, pagination.next_page));
1345
- }
1579
+ // The linter thinks query.data is always falsy, but we know it can be defined after a successful query
1580
+ // Let's restructure to avoid the conditional
1581
+ const paginationData = query.data && getPaginationData(query.data);
1582
+ if (!paginationData)
1583
+ return;
1584
+ if (paginationData.next_page !== paginationData.current_page &&
1585
+ paginationData.next_page > paginationData.current_page) {
1586
+ setRequestPath(constructPaginationLink(requestPath, paginationData.next_page));
1346
1587
  }
1347
1588
  };
1589
+ /**
1590
+ * Navigate to the previous page if available
1591
+ */
1348
1592
  const prevPage = () => {
1349
- if (query.data.data.pagination) {
1350
- const pagination = query.data.data.pagination;
1351
- if (pagination.previous_page !== pagination.current_page && pagination.previous_page < pagination.current_page) {
1352
- setRequestPath(constructPaginationLink(requestPath, pagination.previous_page));
1353
- }
1593
+ // The linter thinks query.data is always falsy, but we know it can be defined after a successful query
1594
+ // Let's restructure to avoid the conditional
1595
+ const paginationData = query.data && getPaginationData(query.data);
1596
+ if (!paginationData)
1597
+ return;
1598
+ if (paginationData.previous_page !== paginationData.current_page &&
1599
+ paginationData.previous_page < paginationData.current_page) {
1600
+ setRequestPath(constructPaginationLink(requestPath, paginationData.previous_page));
1354
1601
  }
1355
1602
  };
1603
+ /**
1604
+ * Construct a pagination URL using the configured builder
1605
+ */
1356
1606
  const constructPaginationLink = (link, pageNumber) => {
1357
- const [pathname, queryString] = link.split('?');
1358
- const queryParams = new URLSearchParams(queryString);
1359
- const oldPage = Number(queryParams.get('page'));
1360
- queryParams.set('page', pageNumber);
1361
- link = pathname + '?' + queryParams.toString();
1362
- // only update page when pagination number changed
1363
- if (oldPage !== pageNumber) {
1364
- setPage(pageNumber);
1365
- }
1366
- return link;
1607
+ // Use the configured pagination URL builder or fall back to default
1608
+ const buildPaginationUrl = pagination.buildPaginationUrl ||
1609
+ ((url, page) => {
1610
+ const [pathname, queryString] = url.split('?');
1611
+ const queryParams = new URLSearchParams(queryString || '');
1612
+ const pageParamName = pagination.pageParamName || 'page';
1613
+ const oldPage = Number(queryParams.get(pageParamName));
1614
+ queryParams.set(pageParamName, String(page));
1615
+ const newUrl = pathname + '?' + queryParams.toString();
1616
+ // only update page when pagination number changed
1617
+ if (oldPage !== pageNumber) {
1618
+ setPage(pageNumber);
1619
+ }
1620
+ return newUrl;
1621
+ });
1622
+ return buildPaginationUrl(link, pageNumber);
1367
1623
  };
1624
+ /**
1625
+ * Navigate to a specific page
1626
+ */
1368
1627
  const gotoPage = (pageNumber) => {
1369
1628
  setRequestPath(constructPaginationLink(requestPath, pageNumber));
1370
1629
  };
@@ -1406,6 +1665,10 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
1406
1665
  gotoPage,
1407
1666
  page,
1408
1667
  queryKey: [requestPath, {}],
1668
+ // Add pagination data accessor - restructured to avoid linter error
1669
+ getPaginationData: function () {
1670
+ return query.data ? getPaginationData(query.data) : undefined;
1671
+ },
1409
1672
  };
1410
1673
  };
1411
1674
 
@@ -1415,7 +1678,7 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
1415
1678
  const globalHeaders = useHeaderStore((state) => state.headers);
1416
1679
  const [requestPayload, setRequestPayload] = useState();
1417
1680
  const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
1418
- const { middleware, context } = useStore(bootStore);
1681
+ const { context } = useStore(bootStore);
1419
1682
  const sendRequest = async (res, rej, data) => {
1420
1683
  // get request headers
1421
1684
  const requestOptions = {
@@ -1427,19 +1690,24 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
1427
1690
  timeout: TIMEOUT,
1428
1691
  onUploadProgress,
1429
1692
  };
1430
- let patchResponse;
1431
- if (middleware) {
1432
- // perform global middleware
1433
- const middlewareResponse = await middleware(async (options) => await makeRequest(options ? { ...requestOptions, ...options } : requestOptions), {
1434
- path,
1435
- baseUrl: baseUrl ?? API_URL,
1436
- body: data,
1437
- });
1438
- patchResponse = middlewareResponse;
1439
- }
1440
- else {
1441
- patchResponse = await makeRequest(requestOptions);
1442
- }
1693
+ // let patchResponse: IRequestError | IRequestSuccess<TResponse>;
1694
+ // if (middleware) {
1695
+ // // perform global middleware
1696
+ // const middlewareResponse = await middleware(
1697
+ // async (options) =>
1698
+ // await makeRequest<TResponse>(
1699
+ // options ? { ...requestOptions, ...options } : requestOptions
1700
+ // ),
1701
+ // {
1702
+ // path,
1703
+ // baseUrl: baseUrl ?? API_URL,
1704
+ // body: data,
1705
+ // }
1706
+ // );
1707
+ // patchResponse = middlewareResponse;
1708
+ // } else {
1709
+ const patchResponse = await makeRequest(requestOptions);
1710
+ // }
1443
1711
  if (patchResponse.status) {
1444
1712
  // scroll to top after success
1445
1713
  if (context !== 'app') {
@@ -1483,7 +1751,7 @@ const usePatchRequest = ({ path, baseUrl, headers }) => {
1483
1751
 
1484
1752
  const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelectors, }) => {
1485
1753
  const { API_URL, TIMEOUT } = useEnvironmentVariables();
1486
- const { middleware, context } = useStore(bootStore);
1754
+ const { context } = useStore(bootStore);
1487
1755
  const globalHeaders = useHeaderStore((state) => state.headers);
1488
1756
  const { isApp } = useReactNativeEnv();
1489
1757
  const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
@@ -1508,18 +1776,23 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
1508
1776
  onUploadProgress,
1509
1777
  ...requestConfig,
1510
1778
  };
1511
- let postResponse;
1512
- if (middleware) {
1513
- // perform global middleware
1514
- postResponse = await middleware(async (options) => await makeRequest(options ? { ...requestOptions, ...options } : requestOptions), {
1515
- path,
1516
- baseUrl: baseUrl ?? API_URL,
1517
- body: data,
1518
- });
1519
- }
1520
- else {
1521
- postResponse = await makeRequest(requestOptions);
1522
- }
1779
+ // let postResponse: IRequestError | IRequestSuccess<TResponse>;
1780
+ // if (middleware) {
1781
+ // // perform global middleware
1782
+ // postResponse = await middleware(
1783
+ // async (options) =>
1784
+ // await makeRequest<TResponse>(
1785
+ // options ? { ...requestOptions, ...options } : requestOptions
1786
+ // ),
1787
+ // {
1788
+ // path,
1789
+ // baseUrl: baseUrl ?? API_URL,
1790
+ // body: data,
1791
+ // }
1792
+ // );
1793
+ // } else {
1794
+ const postResponse = await makeRequest(requestOptions);
1795
+ // }
1523
1796
  if (postResponse.status) {
1524
1797
  // scroll to top after success
1525
1798
  if (context !== 'app') {
@@ -1560,5 +1833,5 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
1560
1833
  return { post, uploadProgressPercent, ...mutation, isLoading: mutation.isPending || isFutureMutationsPaused };
1561
1834
  };
1562
1835
 
1563
- export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useBaseUrlStore, useDeleteRequest, useEnvironmentVariables, useGetInfiniteRequest, useGetRequest, useHeaderStore, useKeyTrackerModel, usePatchRequest, usePauseFutureRequests, usePostRequest, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery, useUploadProgress };
1836
+ export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, executeMiddlewareChain, getDateInFuture, makeRequest, result, scrollToTop, successTransformer, useBaseUrlStore, useDeleteRequest, useEnvironmentVariables, useGetInfiniteRequest, useGetRequest, useHeaderStore, useKeyTrackerModel, usePatchRequest, usePauseFutureRequests, usePostRequest, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery, useUploadProgress };
1564
1837
  //# sourceMappingURL=index.mjs.map