@react-xp/fetch 1.0.0-beta.2 → 1.0.0-beta.4

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 (69) hide show
  1. package/dist/cjs/fetchContext.js +26 -0
  2. package/dist/cjs/fetchCore.js +58 -0
  3. package/dist/cjs/fetchProvider.js +46 -0
  4. package/dist/cjs/fetchTypes.js +0 -1
  5. package/dist/cjs/index.js +3 -4
  6. package/dist/cjs/useFetchContext.js +28 -0
  7. package/dist/cjs/useFetchCore.js +229 -0
  8. package/dist/cjs/useFetchMutation.js +46 -13
  9. package/dist/cjs/useFetchQuery.js +34 -12
  10. package/dist/cjs/useFetchUtils.js +45 -0
  11. package/dist/esm/fetchContext.js +23 -0
  12. package/dist/esm/fetchCore.js +54 -0
  13. package/dist/esm/fetchProvider.js +42 -0
  14. package/dist/esm/fetchTypes.js +0 -1
  15. package/dist/esm/index.js +3 -4
  16. package/dist/esm/useFetchContext.js +21 -0
  17. package/dist/esm/useFetchCore.js +225 -0
  18. package/dist/esm/useFetchMutation.js +46 -13
  19. package/dist/esm/useFetchQuery.js +34 -12
  20. package/dist/esm/useFetchUtils.js +41 -0
  21. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  22. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  23. package/dist/types/fetchContext.d.ts +15 -0
  24. package/dist/types/fetchContext.d.ts.map +1 -0
  25. package/dist/types/fetchCore.d.ts +17 -0
  26. package/dist/types/fetchCore.d.ts.map +1 -0
  27. package/dist/types/fetchProvider.d.ts +26 -0
  28. package/dist/types/fetchProvider.d.ts.map +1 -0
  29. package/dist/types/fetchTypes.d.ts +130 -46
  30. package/dist/types/fetchTypes.d.ts.map +1 -1
  31. package/dist/types/index.d.ts +3 -3
  32. package/dist/types/index.d.ts.map +1 -1
  33. package/dist/types/useFetchContext.d.ts +11 -0
  34. package/dist/types/useFetchContext.d.ts.map +1 -0
  35. package/dist/types/useFetchCore.d.ts +60 -0
  36. package/dist/types/useFetchCore.d.ts.map +1 -0
  37. package/dist/types/useFetchMutation.d.ts +30 -25
  38. package/dist/types/useFetchMutation.d.ts.map +1 -1
  39. package/dist/types/useFetchQuery.d.ts +27 -24
  40. package/dist/types/useFetchQuery.d.ts.map +1 -1
  41. package/dist/types/useFetchUtils.d.ts +18 -0
  42. package/dist/types/useFetchUtils.d.ts.map +1 -0
  43. package/package.json +11 -8
  44. package/dist/cjs/fetchHelper.js +0 -179
  45. package/dist/cjs/fetchHelper.js.map +0 -1
  46. package/dist/cjs/fetchModule.js +0 -14
  47. package/dist/cjs/fetchModule.js.map +0 -1
  48. package/dist/cjs/fetchTypes.js.map +0 -1
  49. package/dist/cjs/index.js.map +0 -1
  50. package/dist/cjs/useFetch.js +0 -99
  51. package/dist/cjs/useFetch.js.map +0 -1
  52. package/dist/cjs/useFetchMutation.js.map +0 -1
  53. package/dist/cjs/useFetchQuery.js.map +0 -1
  54. package/dist/esm/fetchHelper.js +0 -176
  55. package/dist/esm/fetchHelper.js.map +0 -1
  56. package/dist/esm/fetchModule.js +0 -10
  57. package/dist/esm/fetchModule.js.map +0 -1
  58. package/dist/esm/fetchTypes.js.map +0 -1
  59. package/dist/esm/index.js.map +0 -1
  60. package/dist/esm/useFetch.js +0 -92
  61. package/dist/esm/useFetch.js.map +0 -1
  62. package/dist/esm/useFetchMutation.js.map +0 -1
  63. package/dist/esm/useFetchQuery.js.map +0 -1
  64. package/dist/types/fetchHelper.d.ts +0 -19
  65. package/dist/types/fetchHelper.d.ts.map +0 -1
  66. package/dist/types/fetchModule.d.ts +0 -5
  67. package/dist/types/fetchModule.d.ts.map +0 -1
  68. package/dist/types/useFetch.d.ts +0 -22
  69. package/dist/types/useFetch.d.ts.map +0 -1
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.fetchContext = void 0;
5
+ const react_1 = require("react");
6
+ /**
7
+ * React context for managing fetch configurations and global parameters.
8
+ *
9
+ * @remarks
10
+ * This context provides default values for fetch configurations, a method to retrieve namespace-specific configs,
11
+ * an initialization flag, and a setter for global parameters.
12
+ *
13
+ * @property {Object} configs - Global fetch configurations.
14
+ * @property {Function} getNamespaceConfig - Returns configuration and handlers for a specific namespace.
15
+ * @property {boolean} isInitialized - Indicates if the context has been initialized.
16
+ * @property {Function} setGlobalParameters - Sets global parameters for fetch operations.
17
+ */
18
+ exports.fetchContext = (0, react_1.createContext)({
19
+ configs: {},
20
+ getNamespaceConfig: () => ({
21
+ configs: { baseUrl: 'http://localhost:3000', cache: {} },
22
+ handlers: { onError: () => { } },
23
+ }),
24
+ isInitialized: false,
25
+ setGlobalParameters: () => { },
26
+ });
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchCore = void 0;
4
+ const utils_1 = require("@react-xp/utils");
5
+ const fetchCore = async ({ data, globalParameters, handlers, headers, method, signal, staticResponse, url, }) => {
6
+ const handleOnError = async (error) => {
7
+ // ignore parsing error caused by abort
8
+ if (error === 'user_cancelled' || error?.name === 'AbortError') {
9
+ return {};
10
+ }
11
+ handlers?.onError?.(error, null);
12
+ throw error;
13
+ };
14
+ try {
15
+ handlers?.onRequestStart?.();
16
+ const defaultValues = {
17
+ body: data,
18
+ globalParameters: globalParameters || {},
19
+ headers: headers || {},
20
+ };
21
+ const { body: preparedBody, headers: preparedHeaders } = handlers?.onRequestPrepare?.(defaultValues) || defaultValues;
22
+ const masterUrl = url.replace(/\/+/g, '/').replace(':/', '://');
23
+ const transformedUrl = (0, utils_1.transformTemplateString)({
24
+ template: masterUrl,
25
+ values: {
26
+ ...defaultValues.globalParameters,
27
+ ...preparedBody,
28
+ },
29
+ });
30
+ let res;
31
+ if (staticResponse) {
32
+ res = await staticResponse();
33
+ }
34
+ else {
35
+ const response = await fetch(transformedUrl.value, {
36
+ method,
37
+ headers: preparedHeaders,
38
+ body: preparedBody ? JSON.stringify(preparedBody) : undefined,
39
+ signal,
40
+ });
41
+ if (!response.ok) {
42
+ return handleOnError(response);
43
+ }
44
+ res = await response.json();
45
+ }
46
+ if (res.metadata?.status?.toLowerCase() === 'error') {
47
+ return handleOnError(res);
48
+ }
49
+ return res;
50
+ }
51
+ catch (error) {
52
+ return handleOnError(error);
53
+ }
54
+ finally {
55
+ handlers?.onRequestEnd?.();
56
+ }
57
+ };
58
+ exports.fetchCore = fetchCore;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FetchProvider = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_query_1 = require("@tanstack/react-query");
6
+ const fetchContext_1 = require("./fetchContext");
7
+ const queryClient = new react_query_1.QueryClient();
8
+ const _namespaceConfigs = {};
9
+ /**
10
+ * Provides fetch configuration and handlers for a specific namespace to its child components.
11
+ *
12
+ * This provider initializes and manages fetch-related context, including configuration and handlers,
13
+ * for a given namespace. It ensures that the context is properly initialized before rendering children,
14
+ * and exposes methods to get namespace-specific configuration and set global parameters.
15
+ *
16
+ * @param {FetchProviderProps} props - The properties for the FetchProvider component.
17
+ * @param {React.ReactNode} props.children - The child components to be rendered within the provider.
18
+ * @param {TFetchConfigForNamespace} props.configs - The fetch configuration for the specified namespace.
19
+ * @param {any} props.handlers - The handlers associated with the fetch configuration.
20
+ * @param {TFetchNamespaces} props.namespace - The namespace for which the fetch configuration applies.
21
+ *
22
+ * @throws {Error} If the requested namespace configuration is not found.
23
+ *
24
+ * @returns {JSX.Element} The provider wrapping its children with the fetch context and query client provider.
25
+ */
26
+ const FetchProvider = ({ children, configs, handlers, namespace, }) => {
27
+ _namespaceConfigs[namespace] = { configs, handlers };
28
+ const handleGetNamespaceConfig = (namespace) => {
29
+ if (!Object.getOwnPropertyNames(_namespaceConfigs).includes(namespace)) {
30
+ throw new Error(`FetchProvider: namespace "${namespace}" not found! Make sure to use the correct namespace or to wrap your component tree with a FetchProvider with the correct namespace.`);
31
+ }
32
+ return _namespaceConfigs[namespace];
33
+ };
34
+ const handleSetGlobalParameters = (namespace, globalParameters) => {
35
+ if (_namespaceConfigs?.[namespace]) {
36
+ _namespaceConfigs[namespace].configs.globalParameters = globalParameters;
37
+ }
38
+ };
39
+ return ((0, jsx_runtime_1.jsx)(fetchContext_1.fetchContext.Provider, { value: {
40
+ configs: _namespaceConfigs,
41
+ getNamespaceConfig: handleGetNamespaceConfig,
42
+ isInitialized: true,
43
+ setGlobalParameters: handleSetGlobalParameters,
44
+ }, children: (0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: children }) }));
45
+ };
46
+ exports.FetchProvider = FetchProvider;
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=fetchTypes.js.map
package/dist/cjs/index.js CHANGED
@@ -14,10 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./fetchHelper"), exports);
18
- __exportStar(require("./fetchModule"), exports);
17
+ __exportStar(require("./fetchCore"), exports);
18
+ __exportStar(require("./fetchProvider"), exports);
19
19
  __exportStar(require("./fetchTypes"), exports);
20
- __exportStar(require("./useFetch"), exports);
21
20
  __exportStar(require("./useFetchMutation"), exports);
22
21
  __exportStar(require("./useFetchQuery"), exports);
23
- //# sourceMappingURL=index.js.map
22
+ __exportStar(require("./useFetchUtils"), exports);
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.useFetchContext = void 0;
8
+ const react_1 = __importDefault(require("react"));
9
+ const fetchContext_1 = require("./fetchContext");
10
+ /**
11
+ * Custom hook to access the fetch context.
12
+ *
13
+ * This hook retrieves the current fetch context using React's `useContext`.
14
+ * It also checks if the fetch module has been initialized, and logs an error
15
+ * to the console if it has not been initialized.
16
+ *
17
+ * @returns The current fetch context.
18
+ */
19
+ const useFetchContext = () => {
20
+ const context = react_1.default.useContext(fetchContext_1.fetchContext);
21
+ react_1.default.useEffect(() => {
22
+ if (!context.isInitialized) {
23
+ console.error('Fetch module is not initialized! Using FetchProvider to initialized.');
24
+ }
25
+ }, [context]);
26
+ return context;
27
+ };
28
+ exports.useFetchContext = useFetchContext;
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ 'use client';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useFetchCore = void 0;
5
+ const react_1 = require("react");
6
+ const fetchCore_1 = require("./fetchCore");
7
+ const useFetchContext_1 = require("./useFetchContext");
8
+ function composeAbortSignal(...signals) {
9
+ const s = signals.filter(Boolean);
10
+ for (const x of s) {
11
+ if (x.aborted)
12
+ return AbortSignal.abort(x.reason);
13
+ }
14
+ const ctrl = new AbortController();
15
+ const onAbort = (ev) => {
16
+ if (!ctrl.signal.aborted) {
17
+ ctrl.abort(ev?.target?.reason ?? 'aborted');
18
+ }
19
+ };
20
+ for (const x of s) {
21
+ x.addEventListener('abort', onAbort, { once: true });
22
+ }
23
+ return ctrl.signal;
24
+ }
25
+ /**
26
+ * Custom React hook for performing fetch operations with advanced configuration and lifecycle handlers.
27
+ *
28
+ * @template TInput - The type of the input data for the fetch request.
29
+ * @template TOutput - The type of the output data expected from the fetch response. Must extend `TFetchDefaultOutput`.
30
+ * @template TTransformOutput - The type of the transformed output data. Defaults to `TOutput`.
31
+ *
32
+ * @param params - The configuration object for the fetch operation.
33
+ * @param params.data - The input data to be sent with the request.
34
+ * @param params.key - Unique key for caching and query identification.
35
+ * @param params.method - HTTP method to use for the request (default: 'GET').
36
+ * @param params.namespace - Namespace for fetching configuration and handlers.
37
+ * @param params.onError - Optional callback invoked on error response.
38
+ * @param params.onSuccess - Optional callback invoked on successful response.
39
+ * @param params.options - Additional options for fetch behavior, caching, and loading indicators.
40
+ * @param params.path - API endpoint path to be appended to the base URL.
41
+ * @param params.transform - Optional function to transform the response data.
42
+ *
43
+ * @returns An object containing utility functions:
44
+ * - `getBaseReactQueryInput`: Returns base configuration for React Query hooks.
45
+ * - `getCommonFetchResponse`: Normalizes fetch/mutation responses for consistent usage.
46
+ * - `getFetchTreatment`: Executes the fetch request with configured handlers and returns the processed result.
47
+ * - `onSuccess`: Handles invocation of the success callback, ensuring it is called only once per request.
48
+ *
49
+ * @remarks
50
+ * - Integrates with a context-based configuration system for headers, global parameters, and error handling.
51
+ * - Supports aborting requests and custom loading indicators.
52
+ * - Designed for use with React Query and custom fetch logic in modular applications.
53
+ */
54
+ const useFetchCore = ({ data: inputData, key, method = 'GET', namespace, onError, onSuccess, options, path, select, staticResponse, }) => {
55
+ const { getNamespaceConfig } = (0, useFetchContext_1.useFetchContext)();
56
+ const fetchConfigs = getNamespaceConfig(namespace);
57
+ const lastDataUpdatedAt = (0, react_1.useRef)(0);
58
+ const fetchSignal = (0, react_1.useRef)(new AbortController());
59
+ const handleGetBaseReactQueryInput = () => ({
60
+ enabled: options?.enabled ?? true,
61
+ gcTime: (options?.cache?.cacheTime ||
62
+ fetchConfigs.configs.cache?.cacheTime ||
63
+ 0) * 1000,
64
+ queryKey: [key, inputData],
65
+ mutationKey: [key],
66
+ select: (data) => select?.(data, inputData) || data,
67
+ staleTime: (options?.cache?.staleTime ||
68
+ fetchConfigs.configs.cache?.staleTime ||
69
+ 0) * 1000,
70
+ });
71
+ // const handleGetFetchTreatment = async ({
72
+ // body,
73
+ // signal,
74
+ // }: { body?: TAny; signal?: AbortSignal }) => {
75
+ // const handleOnError = (error: TAny) => {
76
+ // // ignore parsing error caused by abort
77
+ // if (error === 'user_cancelled' || error?.name === 'AbortError') {
78
+ // return {} as TTransformOutput;
79
+ // }
80
+ // if (onError) {
81
+ // const raiseUp = onError(error, null);
82
+ // if (raiseUp) {
83
+ // fetchConfigs.handlers.onError(error);
84
+ // }
85
+ // } else {
86
+ // fetchConfigs.handlers.onError(error);
87
+ // }
88
+ // throw error;
89
+ // };
90
+ // try {
91
+ // fetchConfigs.handlers.onRequestStart?.({
92
+ // showLoading: options?.showLoading || false,
93
+ // });
94
+ // const combinedSignal =
95
+ // (AbortSignal as TAny).any?.(
96
+ // [fetchSignal.current.signal, signal].filter(Boolean),
97
+ // ) ?? composeAbortSignal(fetchSignal.current.signal, signal);
98
+ // const defaultValues: TFetchHandlersOnRequestPrepareIn = {
99
+ // body: body || inputData,
100
+ // globalParameters: fetchConfigs.configs.globalParameters || {},
101
+ // headers: fetchConfigs.configs.headers || {},
102
+ // };
103
+ // const { body: preparedBody, headers: preparedHeaders } =
104
+ // fetchConfigs.handlers.onRequestPrepare?.(defaultValues) ||
105
+ // defaultValues;
106
+ // const url = `${fetchConfigs.configs.baseUrl}/${path}`
107
+ // .replace(/\/+/g, '/')
108
+ // .replace(':/', '://');
109
+ // const transformedUrl = transformTemplateString({
110
+ // template: url,
111
+ // values: {
112
+ // ...defaultValues.globalParameters,
113
+ // ...preparedBody,
114
+ // },
115
+ // });
116
+ // console.log('useFetchCore :: handleGetFetchTreatment :: url', {
117
+ // url,
118
+ // transformedUrl,
119
+ // values: { ...defaultValues.globalParameters, preparedBody },
120
+ // });
121
+ // const response = await fetch(transformedUrl.value, {
122
+ // method,
123
+ // headers: preparedHeaders,
124
+ // body: preparedBody ? JSON.stringify(preparedBody) : undefined,
125
+ // signal: combinedSignal,
126
+ // });
127
+ // if (!response.ok) {
128
+ // return handleOnError(response);
129
+ // }
130
+ // const res = await response.json();
131
+ // if (res.metadata?.status?.toLowerCase() === 'error') {
132
+ // return handleOnError(res);
133
+ // }
134
+ // return res;
135
+ // } catch (error) {
136
+ // return handleOnError(error);
137
+ // } finally {
138
+ // fetchConfigs.handlers.onRequestEnd?.({
139
+ // showLoading: options?.showLoading || false,
140
+ // });
141
+ // }
142
+ // };
143
+ const handleGetFetchTreatment = async ({ body, signal, }) => {
144
+ const combinedSignal = AbortSignal.any?.([fetchSignal.current.signal, signal].filter(Boolean)) ?? composeAbortSignal(fetchSignal.current.signal, signal);
145
+ return (0, fetchCore_1.fetchCore)({
146
+ data: body || inputData,
147
+ globalParameters: fetchConfigs.configs.globalParameters || {},
148
+ handlers: {
149
+ onError: (error) => {
150
+ if (onError) {
151
+ const raiseUp = onError(error, null);
152
+ if (raiseUp) {
153
+ fetchConfigs.handlers.onError(error);
154
+ }
155
+ }
156
+ else {
157
+ fetchConfigs.handlers.onError(error);
158
+ }
159
+ },
160
+ onRequestEnd: () => {
161
+ fetchConfigs.handlers.onRequestEnd?.({
162
+ showLoading: options?.showLoading || false,
163
+ });
164
+ },
165
+ onRequestStart: () => {
166
+ fetchConfigs.handlers.onRequestStart?.({
167
+ showLoading: options?.showLoading || false,
168
+ });
169
+ },
170
+ onRequestPrepare: (input) => {
171
+ const defaultValues = {
172
+ body: input.body,
173
+ globalParameters: input.globalParameters,
174
+ headers: input.headers,
175
+ };
176
+ return (fetchConfigs.handlers.onRequestPrepare?.(defaultValues) ||
177
+ defaultValues);
178
+ },
179
+ },
180
+ headers: fetchConfigs.configs.headers || {},
181
+ method,
182
+ signal: combinedSignal,
183
+ staticResponse,
184
+ url: `${fetchConfigs.configs.baseUrl}/${path}`,
185
+ });
186
+ };
187
+ const handleOnSuccess = (type, { data, dataUpdatedAt, isSuccess, }, { inputData }) => {
188
+ // console.log(`[DEBUG] useFetchCore :: ${path} :: handleOnSuccess check if is to call`, {
189
+ // data,
190
+ // isSuccess,
191
+ // });
192
+ // only call onSuccess if dataUpdatedAt is newer than last call (to avoid double calls)
193
+ if (((type === 'query' && lastDataUpdatedAt.current < (dataUpdatedAt || 0)) ||
194
+ type === 'mutation') &&
195
+ isSuccess &&
196
+ onSuccess) {
197
+ // console.log(`[DEBUG] useFetchCore :: ${path} :: handleOnSuccess called`, {
198
+ // data,
199
+ // isSuccess,
200
+ // });
201
+ lastDataUpdatedAt.current = dataUpdatedAt || 0;
202
+ onSuccess(data, { inputData });
203
+ }
204
+ };
205
+ const handleGetCommonFetchResponse = ({ data, error, isError, isPending, isSuccess, status, }) => {
206
+ return {
207
+ cancel: () => {
208
+ if (fetchSignal.current) {
209
+ fetchSignal.current.abort('user_cancelled');
210
+ }
211
+ },
212
+ data: data?.data,
213
+ error,
214
+ isError,
215
+ isPending,
216
+ isSuccess,
217
+ response: data,
218
+ status,
219
+ };
220
+ };
221
+ return {
222
+ getBaseReactQueryInput: handleGetBaseReactQueryInput,
223
+ getCommonFetchResponse: handleGetCommonFetchResponse,
224
+ getFetchTreatment: handleGetFetchTreatment,
225
+ getLastResponseKey: () => [`${key}::lastResponse`],
226
+ onSuccess: handleOnSuccess,
227
+ };
228
+ };
229
+ exports.useFetchCore = useFetchCore;
@@ -1,19 +1,52 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.useFetchMutation = void 0;
4
- const useFetch_1 = require("./useFetch");
5
- const useFetchMutation = (input) => {
6
- const ret = (0, useFetch_1.useFetch)(input);
7
- const transformedRet = {
8
- abort: ret.abort,
9
- data$: ret.data$,
10
- error$: ret.error$,
11
- isFetching$: ret.isFetching$,
12
- mutate: ret.fetch,
13
- response$: ret.response$,
14
- status$: ret.status$,
5
+ const react_query_1 = require("@tanstack/react-query");
6
+ const useFetchCore_1 = require("./useFetchCore");
7
+ /**
8
+ * Custom React hook for performing mutations using React Query and a fetch-based treatment.
9
+ *
10
+ * @template TInput - The type of the mutation input.
11
+ * @template TOutput - The type of the mutation output, extending `TFetchDefaultOutput`.
12
+ * @template TTransformOutput - The type of the transformed mutation output, extending `TFetchDefaultOutput`. Defaults to `TOutput`.
13
+ *
14
+ * @param props - The input properties for configuring the mutation, including fetch logic and success handling.
15
+ * @returns An object containing the common fetch response, mutation functions (`mutate`, `mutateAsync`), and additional mutation state.
16
+ *
17
+ * @remarks
18
+ * - Uses `useMutation` from React Query to handle mutation logic.
19
+ * - Integrates with custom fetch treatment and response transformation.
20
+ * - Calls `onSuccess` callback when the mutation succeeds.
21
+ */
22
+ const useFetchMutation = (props) => {
23
+ const queryClient = (0, react_query_1.useQueryClient)();
24
+ const { getBaseReactQueryInput, getCommonFetchResponse, getFetchTreatment, getLastResponseKey, onSuccess, } = (0, useFetchCore_1.useFetchCore)(props);
25
+ const res = (0, react_query_1.useMutation)({
26
+ ...getBaseReactQueryInput(),
27
+ mutationFn: async (body) => {
28
+ return getFetchTreatment({ body });
29
+ },
30
+ onSuccess: (data, variables) => {
31
+ queryClient.setQueryData(getLastResponseKey(), data);
32
+ onSuccess('mutation', { data, isSuccess: true }, { inputData: variables });
33
+ },
34
+ });
35
+ return {
36
+ ...getCommonFetchResponse(res),
37
+ getLastResponse: () => {
38
+ const response = queryClient.getQueryData(getLastResponseKey());
39
+ return {
40
+ data: response?.data,
41
+ response,
42
+ };
43
+ },
44
+ mutate: (data) => {
45
+ return res.mutate(data);
46
+ },
47
+ mutateAsync: (data) => {
48
+ return res.mutateAsync(data);
49
+ },
15
50
  };
16
- return transformedRet;
17
51
  };
18
52
  exports.useFetchMutation = useFetchMutation;
19
- //# sourceMappingURL=useFetchMutation.js.map
@@ -1,18 +1,40 @@
1
1
  "use strict";
2
+ 'use client';
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.useFetchQuery = void 0;
4
- const merge_1 = require("@react-xp/merge");
5
- const fetchHelper_1 = require("./fetchHelper");
6
- const useFetch_1 = require("./useFetch");
7
- const useFetchQuery = (input) => {
8
- const deepMerge = (0, merge_1.useDeepMerge)();
9
- const configs = fetchHelper_1.fetchHelper.configs();
10
- return (0, useFetch_1.useFetch)(deepMerge(input, {
11
- options: {
12
- callOnMount: true,
13
- cache: input.options?.cache || configs.options?.cache,
5
+ const react_query_1 = require("@tanstack/react-query");
6
+ const react_1 = require("react");
7
+ const useFetchCore_1 = require("./useFetchCore");
8
+ /**
9
+ * Custom React hook for fetching data using React Query with enhanced configuration and response handling.
10
+ *
11
+ * @template TInput - The type of the input parameters for the fetch query.
12
+ * @template TOutput - The type of the output returned by the fetch query. Must extend `TFetchDefaultOutput`.
13
+ * @template TTransformOutput - The type of the transformed output returned by the query function. Defaults to `TOutput`.
14
+ *
15
+ * @param props - The input properties required to configure the fetch query, including query parameters and transformation logic.
16
+ * @returns An object containing the common fetch response, including data, status, error, and a `refetch` function.
17
+ *
18
+ * @remarks
19
+ * - Utilizes `useFetchCore` for shared fetch logic and configuration.
20
+ * - Wraps the query function with React Query's `useQuery` for caching and state management.
21
+ * - Executes the `onSuccess` callback whenever the query result changes.
22
+ * - The returned object merges the common fetch response with the `refetch` method from React Query.
23
+ */
24
+ const useFetchQuery = (props) => {
25
+ const { getBaseReactQueryInput, getCommonFetchResponse, getFetchTreatment, onSuccess, } = (0, useFetchCore_1.useFetchCore)(props);
26
+ const res = (0, react_query_1.useQuery)({
27
+ ...getBaseReactQueryInput(),
28
+ queryFn: async ({ signal }) => {
29
+ return getFetchTreatment({ signal });
14
30
  },
15
- }));
31
+ });
32
+ (0, react_1.useEffect)(() => {
33
+ onSuccess('query', res, { inputData: props.data });
34
+ }, [onSuccess, res, props.data]);
35
+ return {
36
+ ...getCommonFetchResponse(res),
37
+ refetch: res.refetch,
38
+ };
16
39
  };
17
40
  exports.useFetchQuery = useFetchQuery;
18
- //# sourceMappingURL=useFetchQuery.js.map
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFetchUtils = void 0;
4
+ const react_query_1 = require("@tanstack/react-query");
5
+ const react_1 = require("react");
6
+ const fetchContext_1 = require("./fetchContext");
7
+ /**
8
+ * Custom hook providing utility functions for managing fetch queries and global parameters.
9
+ *
10
+ * @returns An object containing:
11
+ * - `cancelQueries`: Cancels ongoing queries for the specified keys, or all queries if no keys are provided.
12
+ * - `clearCache`: Clears the cache for the specified keys, or clears all cache if no keys are provided.
13
+ * - `setGlobalParameters`: Sets global parameters for fetch operations.
14
+ *
15
+ * @remarks
16
+ * This hook leverages the query client and fetch context to provide centralized query management utilities.
17
+ */
18
+ const useFetchUtils = () => {
19
+ const queryClient = (0, react_query_1.useQueryClient)();
20
+ const { setGlobalParameters } = (0, react_1.useContext)(fetchContext_1.fetchContext);
21
+ return (0, react_1.useMemo)(() => ({
22
+ cancelQueries: (keys = undefined) => {
23
+ if (!keys || keys.length === 0) {
24
+ queryClient.cancelQueries();
25
+ }
26
+ else {
27
+ for (const key of keys) {
28
+ queryClient.cancelQueries({ queryKey: key });
29
+ }
30
+ }
31
+ },
32
+ clearCache: (keys = undefined) => {
33
+ if (!keys || keys.length === 0) {
34
+ queryClient.invalidateQueries();
35
+ }
36
+ else {
37
+ for (const key of keys) {
38
+ queryClient.invalidateQueries({ queryKey: key });
39
+ }
40
+ }
41
+ },
42
+ setGlobalParameters,
43
+ }), [queryClient, setGlobalParameters]);
44
+ };
45
+ exports.useFetchUtils = useFetchUtils;
@@ -0,0 +1,23 @@
1
+ 'use client';
2
+ import { createContext } from 'react';
3
+ /**
4
+ * React context for managing fetch configurations and global parameters.
5
+ *
6
+ * @remarks
7
+ * This context provides default values for fetch configurations, a method to retrieve namespace-specific configs,
8
+ * an initialization flag, and a setter for global parameters.
9
+ *
10
+ * @property {Object} configs - Global fetch configurations.
11
+ * @property {Function} getNamespaceConfig - Returns configuration and handlers for a specific namespace.
12
+ * @property {boolean} isInitialized - Indicates if the context has been initialized.
13
+ * @property {Function} setGlobalParameters - Sets global parameters for fetch operations.
14
+ */
15
+ export const fetchContext = createContext({
16
+ configs: {},
17
+ getNamespaceConfig: () => ({
18
+ configs: { baseUrl: 'http://localhost:3000', cache: {} },
19
+ handlers: { onError: () => { } },
20
+ }),
21
+ isInitialized: false,
22
+ setGlobalParameters: () => { },
23
+ });
@@ -0,0 +1,54 @@
1
+ import { transformTemplateString } from '@react-xp/utils';
2
+ export const fetchCore = async ({ data, globalParameters, handlers, headers, method, signal, staticResponse, url, }) => {
3
+ const handleOnError = async (error) => {
4
+ // ignore parsing error caused by abort
5
+ if (error === 'user_cancelled' || error?.name === 'AbortError') {
6
+ return {};
7
+ }
8
+ handlers?.onError?.(error, null);
9
+ throw error;
10
+ };
11
+ try {
12
+ handlers?.onRequestStart?.();
13
+ const defaultValues = {
14
+ body: data,
15
+ globalParameters: globalParameters || {},
16
+ headers: headers || {},
17
+ };
18
+ const { body: preparedBody, headers: preparedHeaders } = handlers?.onRequestPrepare?.(defaultValues) || defaultValues;
19
+ const masterUrl = url.replace(/\/+/g, '/').replace(':/', '://');
20
+ const transformedUrl = transformTemplateString({
21
+ template: masterUrl,
22
+ values: {
23
+ ...defaultValues.globalParameters,
24
+ ...preparedBody,
25
+ },
26
+ });
27
+ let res;
28
+ if (staticResponse) {
29
+ res = await staticResponse();
30
+ }
31
+ else {
32
+ const response = await fetch(transformedUrl.value, {
33
+ method,
34
+ headers: preparedHeaders,
35
+ body: preparedBody ? JSON.stringify(preparedBody) : undefined,
36
+ signal,
37
+ });
38
+ if (!response.ok) {
39
+ return handleOnError(response);
40
+ }
41
+ res = await response.json();
42
+ }
43
+ if (res.metadata?.status?.toLowerCase() === 'error') {
44
+ return handleOnError(res);
45
+ }
46
+ return res;
47
+ }
48
+ catch (error) {
49
+ return handleOnError(error);
50
+ }
51
+ finally {
52
+ handlers?.onRequestEnd?.();
53
+ }
54
+ };