@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.
- package/dist/config/bootstrapQueryRequest.d.ts +6 -0
- package/dist/config/useEnvironmentVariables.d.ts +4 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/result.d.ts +23 -0
- package/dist/index.mjs +368 -95
- package/dist/index.mjs.map +1 -1
- package/dist/node_modules/@tanstack/react-store/dist/esm/index.js +1 -1
- 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
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js.map +1 -0
- 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
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js.map +1 -0
- 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
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +1 -0
- 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
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/index.js +1 -1
- package/dist/node_modules/use-sync-external-store/shim/index.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/with-selector.js +1 -1
- package/dist/node_modules/use-sync-external-store/shim/with-selector.js.map +1 -0
- package/dist/queries/useGetRequest.d.ts +12 -2
- package/dist/request/make-request.d.ts +12 -1
- package/dist/src/config/bootstrapQueryRequest.js +41 -1
- package/dist/src/config/bootstrapQueryRequest.js.map +1 -1
- package/dist/src/config/useEnvironmentVariables.js +35 -4
- package/dist/src/config/useEnvironmentVariables.js.map +1 -1
- package/dist/src/helpers/result.js +59 -0
- package/dist/src/helpers/result.js.map +1 -0
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/model/useQueryModel.js +1 -1
- package/dist/src/queries/useDeleteRequest.js +19 -14
- package/dist/src/queries/useDeleteRequest.js.map +1 -1
- package/dist/src/queries/useGetInfiniteRequest.js +17 -12
- package/dist/src/queries/useGetInfiniteRequest.js.map +1 -1
- package/dist/src/queries/useGetRequest.js +86 -28
- package/dist/src/queries/useGetRequest.js.map +1 -1
- package/dist/src/queries/usePatchRequest.js +19 -14
- package/dist/src/queries/usePatchRequest.js.map +1 -1
- package/dist/src/queries/usePostRequest.js +18 -13
- package/dist/src/queries/usePostRequest.js.map +1 -1
- package/dist/src/request/make-request.js +75 -6
- package/dist/src/request/make-request.js.map +1 -1
- package/dist/types/index.d.ts +24 -5
- package/package.json +2 -4
- package/src/config/bootstrapQueryRequest.ts +47 -2
- package/src/config/useEnvironmentVariables.ts +42 -4
- package/src/helpers/index.ts +1 -0
- package/src/helpers/result.ts +65 -0
- package/src/model/useQueryModel.ts +2 -2
- package/src/queries/useDeleteRequest.ts +18 -20
- package/src/queries/useGetInfiniteRequest.ts +17 -17
- package/src/queries/useGetRequest.ts +109 -33
- package/src/queries/usePatchRequest.ts +19 -16
- package/src/queries/usePostRequest.ts +18 -15
- package/src/queries/usePutRequest.ts +16 -15
- package/src/request/make-request.ts +112 -15
- package/src/types/index.ts +38 -4
- 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
- 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
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/shim/index.js.map +0 -1
- 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
|
-
//
|
|
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
|
|
726
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1027
|
-
// configure request
|
|
1028
|
-
configureRequestHeader(isFormData, headers, isApp, appFiles,
|
|
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
|
|
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
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
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
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
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
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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
|
-
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
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 {
|
|
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
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
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 {
|
|
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
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
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
|