api-core-lib 16.2.0 → 16.12.134

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/index.cjs ADDED
@@ -0,0 +1,301 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;
2
+
3
+
4
+
5
+
6
+
7
+
8
+ var _chunkJAMEOM7Tcjs = require('./chunk-JAMEOM7T.cjs');
9
+
10
+ // src/core/client.ts
11
+ var _axios = require('axios'); var _axios2 = _interopRequireDefault(_axios);
12
+ var _uuid = require('uuid');
13
+ async function runMiddleware(context, middlewares = []) {
14
+ const run = async (index) => {
15
+ if (index >= middlewares.length) return;
16
+ const middleware = middlewares[index];
17
+ await middleware(context, () => run(index + 1));
18
+ };
19
+ await run(0);
20
+ }
21
+ async function refreshToken(config, tokenManager) {
22
+ const { refreshTokenConfig } = config;
23
+ if (!refreshTokenConfig) {
24
+ console.warn("Token refresh is disabled: `refreshTokenConfig` is not provided.");
25
+ await tokenManager.clearTokens();
26
+ return null;
27
+ }
28
+ try {
29
+ const currentTokens = await tokenManager.getTokens();
30
+ if (!currentTokens.refreshToken) {
31
+ throw new Error("No refresh token available to perform refresh.");
32
+ }
33
+ const { path, buildRequestBody, buildRequestHeaders, extractTokens } = refreshTokenConfig;
34
+ const requestBody = buildRequestBody ? buildRequestBody(currentTokens.refreshToken) : { refresh_token: currentTokens.refreshToken };
35
+ const requestHeaders = buildRequestHeaders ? buildRequestHeaders(currentTokens) : {};
36
+ const response = await _axios2.default.post(
37
+ `${config.baseURL}${path}`,
38
+ requestBody,
39
+ { headers: requestHeaders, withCredentials: config.withCredentials }
40
+ );
41
+ const extracted = extractTokens(response.data);
42
+ if (!extracted || !extracted.accessToken || typeof extracted.expiresIn !== "number") {
43
+ throw new Error("extractTokens function failed to return a valid token structure.");
44
+ }
45
+ const newTokens = {
46
+ accessToken: extracted.accessToken,
47
+ refreshToken: extracted.refreshToken || currentTokens.refreshToken,
48
+ expiresAt: Date.now() + extracted.expiresIn * 1e3,
49
+ tokenType: extracted.tokenType || "Bearer"
50
+ };
51
+ await tokenManager.setTokens(newTokens);
52
+ console.info("Tokens refreshed successfully.");
53
+ return newTokens;
54
+ } catch (err) {
55
+ console.error("Failed to refresh token.", _optionalChain([err, 'access', _ => _.response, 'optionalAccess', _2 => _2.data]) || err.message);
56
+ if (config.onRefreshError) {
57
+ config.onRefreshError(err);
58
+ }
59
+ await tokenManager.clearTokens();
60
+ return null;
61
+ }
62
+ }
63
+ function createApiClient(config) {
64
+ const {
65
+ baseURL,
66
+ tokenManager,
67
+ timeout = 15e3,
68
+ headers = {},
69
+ withCredentials = false,
70
+ middleware = [],
71
+ defaultIsPublic = false,
72
+ maxTokenRefreshRetries = 2,
73
+ maxQueueSize = 50,
74
+ onRefreshError
75
+ } = config;
76
+ const axiosInstance = _axios2.default.create({
77
+ baseURL,
78
+ timeout,
79
+ headers: { "Content-Type": "application/json", ...headers },
80
+ withCredentials
81
+ });
82
+ let isRefreshing = false;
83
+ let refreshAttempts = 0;
84
+ let failedQueue = [];
85
+ const processQueue = (error, token = null) => {
86
+ failedQueue.forEach((prom) => error ? prom.reject(error) : prom.resolve(token));
87
+ failedQueue = [];
88
+ };
89
+ const safeRunMiddleware = async (context, middlewareList) => {
90
+ try {
91
+ await runMiddleware(context, middlewareList);
92
+ } catch (err) {
93
+ console.error("Middleware Error", err);
94
+ }
95
+ };
96
+ axiosInstance.interceptors.request.use(async (req) => {
97
+ req.headers["X-Request-ID"] = _uuid.v4.call(void 0, );
98
+ try {
99
+ const fullUrl = _axios2.default.getUri({ ...req, baseURL: _nullishCoalesce(req.baseURL, () => ( baseURL)) });
100
+ console.log(`Request Sent > ${_optionalChain([req, 'access', _3 => _3.method, 'optionalAccess', _4 => _4.toUpperCase, 'call', _5 => _5()])} ${fullUrl}`, `(ID: ${req.headers["X-Request-ID"]})`);
101
+ } catch (e) {
102
+ console.warn("Failed to build full request URL for logging.");
103
+ }
104
+ if (req.upload) {
105
+ delete req.headers["Content-Type"];
106
+ }
107
+ await safeRunMiddleware({ req, custom: {} }, middleware);
108
+ if (_nullishCoalesce(req.isPublic, () => ( defaultIsPublic))) {
109
+ return req;
110
+ }
111
+ if (tokenManager.isHttpOnly()) return req;
112
+ let tokens = await tokenManager.getTokens();
113
+ const now = Date.now();
114
+ const tokenBuffer = 60 * 1e3;
115
+ if (tokens.accessToken && tokens.expiresAt && tokens.expiresAt - now < tokenBuffer && !isRefreshing) {
116
+ if (config.refreshTokenConfig) {
117
+ console.info("Proactive token refresh initiated.");
118
+ isRefreshing = true;
119
+ try {
120
+ const newTokens = await refreshToken(config, tokenManager);
121
+ if (newTokens) tokens = newTokens;
122
+ } catch (err) {
123
+ console.error("Proactive refresh failed", err);
124
+ } finally {
125
+ isRefreshing = false;
126
+ }
127
+ }
128
+ }
129
+ if (tokens.accessToken) {
130
+ req.headers.Authorization = `${tokens.tokenType || "Bearer"} ${tokens.accessToken}`;
131
+ }
132
+ return req;
133
+ });
134
+ axiosInstance.interceptors.response.use(
135
+ async (res) => {
136
+ try {
137
+ const fullUrl = _axios2.default.getUri(res.config);
138
+ console.log(`Response Received < ${_optionalChain([res, 'access', _6 => _6.config, 'access', _7 => _7.method, 'optionalAccess', _8 => _8.toUpperCase, 'call', _9 => _9()])} ${fullUrl}`, `(ID: ${res.config.headers["X-Request-ID"]}, Status: ${res.status})`);
139
+ } catch (e2) {
140
+ console.warn("Failed to build full response URL for logging.");
141
+ }
142
+ await safeRunMiddleware({ req: res.config, res, custom: {} }, middleware);
143
+ return res;
144
+ },
145
+ async (error) => {
146
+ const originalRequest = error.config;
147
+ try {
148
+ const fullUrl = _axios2.default.getUri(originalRequest);
149
+ const method = _optionalChain([originalRequest, 'access', _10 => _10.method, 'optionalAccess', _11 => _11.toUpperCase, 'call', _12 => _12()]);
150
+ const status = _optionalChain([error, 'access', _13 => _13.response, 'optionalAccess', _14 => _14.status]);
151
+ const responseData = _optionalChain([error, 'access', _15 => _15.response, 'optionalAccess', _16 => _16.data]);
152
+ const summary = `Response Error < ${method} ${fullUrl} | Status: ${status || "N/A"}`;
153
+ const apiMessage = _optionalChain([responseData, 'optionalAccess', _17 => _17.message]) || error.message;
154
+ console.error(summary);
155
+ console.error(`> Message: ${apiMessage}`);
156
+ if (error.response) {
157
+ console.groupCollapsed("Full Error Response Details");
158
+ console.dir(error.response.data);
159
+ console.groupEnd();
160
+ }
161
+ } catch (e3) {
162
+ console.error("Response Error: Failed to build full URL for logging.", error.message);
163
+ }
164
+ await safeRunMiddleware({ req: originalRequest, error, custom: {} }, middleware);
165
+ const isHttpOnlyMode = tokenManager.isHttpOnly();
166
+ const canAttemptRefresh = _optionalChain([error, 'access', _18 => _18.response, 'optionalAccess', _19 => _19.status]) === 401 && !originalRequest._retry && config.refreshTokenConfig;
167
+ if (isHttpOnlyMode && canAttemptRefresh) {
168
+ console.error("401 in httpOnly mode. Token refresh must be handled by the server.");
169
+ return Promise.reject(error);
170
+ }
171
+ if (!isHttpOnlyMode && canAttemptRefresh) {
172
+ if (isRefreshing) {
173
+ if (failedQueue.length >= maxQueueSize) {
174
+ console.warn("Failed request queue overflow, rejecting request.");
175
+ return Promise.reject(error);
176
+ }
177
+ return new Promise((resolve, reject) => failedQueue.push({ resolve, reject })).then((token) => {
178
+ originalRequest.headers["Authorization"] = `Bearer ${token}`;
179
+ return axiosInstance(originalRequest);
180
+ });
181
+ }
182
+ if (refreshAttempts >= maxTokenRefreshRetries) {
183
+ console.error("Max token refresh attempts reached.");
184
+ return Promise.reject(error);
185
+ }
186
+ refreshAttempts++;
187
+ originalRequest._retry = true;
188
+ isRefreshing = true;
189
+ try {
190
+ const newTokens = await refreshToken(config, tokenManager);
191
+ if (!_optionalChain([newTokens, 'optionalAccess', _20 => _20.accessToken])) {
192
+ throw new Error("Token refresh failed to produce a new access token.");
193
+ }
194
+ processQueue(null, newTokens.accessToken);
195
+ originalRequest.headers["Authorization"] = `${newTokens.tokenType || "Bearer"} ${newTokens.accessToken}`;
196
+ return axiosInstance(originalRequest);
197
+ } catch (refreshError) {
198
+ processQueue(refreshError, null);
199
+ return Promise.reject(refreshError);
200
+ } finally {
201
+ isRefreshing = false;
202
+ }
203
+ }
204
+ return Promise.reject(error);
205
+ }
206
+ );
207
+ return axiosInstance;
208
+ }
209
+
210
+ // src/services/actions.ts
211
+ function createAction(axiosInstance, method, endpoint) {
212
+ return async (payload, config) => {
213
+ try {
214
+ const response = await axiosInstance.request({
215
+ url: endpoint,
216
+ method,
217
+ ...method.toUpperCase() === "GET" ? { params: payload } : { data: payload },
218
+ ...config
219
+ });
220
+ return _chunkJAMEOM7Tcjs.processResponse.call(void 0, response);
221
+ } catch (error) {
222
+ return _chunkJAMEOM7Tcjs.processResponse.call(void 0, error);
223
+ }
224
+ };
225
+ }
226
+ function createApiActions(axiosInstance, actionsConfig) {
227
+ const actions = {};
228
+ for (const actionName in actionsConfig) {
229
+ if (Object.prototype.hasOwnProperty.call(actionsConfig, actionName)) {
230
+ const { method, endpoint, log } = actionsConfig[actionName];
231
+ actions[actionName] = createAction(axiosInstance, method, endpoint);
232
+ }
233
+ }
234
+ return actions;
235
+ }
236
+
237
+ // src/core/cache.ts
238
+ var CacheManager = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
239
+ __init() {this.cache = /* @__PURE__ */ new Map()}
240
+ __init2() {this.defaultDuration = 15 * 60 * 1e3}
241
+ // 15 minutes
242
+ set(key, data, duration) {
243
+ this.cache.set(key, {
244
+ data,
245
+ timestamp: Date.now(),
246
+ duration: duration || this.defaultDuration
247
+ });
248
+ }
249
+ get(key) {
250
+ const item = this.cache.get(key);
251
+ if (!item) return null;
252
+ const isExpired = Date.now() - item.timestamp > item.duration;
253
+ if (isExpired) {
254
+ this.cache.delete(key);
255
+ return null;
256
+ }
257
+ return item.data;
258
+ }
259
+ /**
260
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
261
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
262
+ */
263
+ getWithMeta(key) {
264
+ const item = this.cache.get(key);
265
+ if (!item) return null;
266
+ const isExpired = Date.now() - item.timestamp > item.duration;
267
+ if (isExpired) {
268
+ this.cache.delete(key);
269
+ return null;
270
+ }
271
+ return item;
272
+ }
273
+ delete(key) {
274
+ this.cache.delete(key);
275
+ }
276
+ clear() {
277
+ this.cache.clear();
278
+ }
279
+ invalidateByPrefix(prefix) {
280
+ const keysToDelete = [];
281
+ for (const key of this.cache.keys()) {
282
+ if (key.startsWith(prefix)) {
283
+ keysToDelete.push(key);
284
+ }
285
+ }
286
+ keysToDelete.forEach((key) => this.cache.delete(key));
287
+ console.log(`Invalidated ${keysToDelete.length} cache entries with prefix: ${prefix}`);
288
+ }
289
+ }, _class);
290
+ var cacheManager = new CacheManager();
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301
+ exports.buildPaginateQuery = _chunkJAMEOM7Tcjs.buildPaginateQuery; exports.cacheManager = cacheManager; exports.callDynamicApi = _chunkJAMEOM7Tcjs.callDynamicApi; exports.createApiActions = createApiActions; exports.createApiClient = createApiClient; exports.createApiServices = _chunkJAMEOM7Tcjs.createApiServices; exports.generateCacheKey = _chunkJAMEOM7Tcjs.generateCacheKey; exports.globalStateManager = _chunkJAMEOM7Tcjs.globalStateManager; exports.processResponse = _chunkJAMEOM7Tcjs.processResponse;
@@ -0,0 +1,225 @@
1
+ import { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse, AxiosError } from 'axios';
2
+ import { e as ApiClientConfig, f as ActionConfigModule, S as StandardResponse, g as ActionOptions, R as RequestConfig, h as ActionStateModule, Q as QueryOptions, i as UseApiQuery, j as ApiError, L as LogLevel } from './apiModule.types-DEskFzOY.cjs';
3
+ export { o as ActionConfig, v as ActionMethods, q as ActionState, u as ActionsWithQuery, A as ApiModuleConfig, E as ExecutableAction, s as ExecuteOptions, I as InputOf, m as Middleware, l as MiddlewareContext, c as ModuleActions, d as ModuleQueries, M as ModuleStates, O as OutputOf, P as PaginationMeta, n as RefreshTokenConfig, k as TokenManager, T as Tokens, r as UrlSyncOptions, U as UseApiConfig, a as UseApiModuleOptions, b as UseApiModuleReturn, p as UseApiState, V as ValidationError, t } from './apiModule.types-DEskFzOY.cjs';
4
+ export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-mpeiDoxm.cjs';
5
+ import 'react';
6
+
7
+ declare function createApiClient(config: ApiClientConfig): AxiosInstance;
8
+
9
+ declare function createApiServices<T>(axiosInstance: AxiosInstance, baseEndpoint: string): {
10
+ get: (id?: string | number, config?: ActionOptions) => Promise<StandardResponse<T>>;
11
+ getWithQuery: (query: string, config?: RequestConfig) => Promise<StandardResponse<T>>;
12
+ post: (data: Partial<T>, config?: ActionOptions) => Promise<StandardResponse<T>>;
13
+ put: (id: string | number, data: T, config?: ActionOptions) => Promise<StandardResponse<T>>;
14
+ patch: (id: string | number, data: Partial<T>, config?: ActionOptions) => Promise<StandardResponse<T>>;
15
+ remove: (id: string | number, config?: ActionOptions) => Promise<StandardResponse<any>>;
16
+ bulkDelete: (ids: Array<string | number>, config?: ActionOptions) => Promise<StandardResponse<any>>;
17
+ upload: (file: File, additionalData?: Record<string, any>, config?: ActionOptions) => Promise<StandardResponse<any>>;
18
+ };
19
+ declare function callDynamicApi(axiosInstance: AxiosInstance, baseEndpoint: string, actionConfig: ActionConfigModule<any, any>, params: {
20
+ pathParams?: Record<string, string | number>;
21
+ body?: any;
22
+ config?: AxiosRequestConfig;
23
+ }): Promise<StandardResponse<any>>;
24
+
25
+ /**
26
+ * Defines a single custom API action.
27
+ * @template TRequest - The type of the data sent in the request body/params.
28
+ * @template TResponse - The type of the data expected in the successful API response.
29
+ */
30
+ type ApiAction<TRequest, TResponse> = (payload: TRequest, config?: RequestConfig) => Promise<StandardResponse<TResponse>>;
31
+ /**
32
+ * A factory function to create a collection of typed, custom API actions.
33
+ *
34
+ * @template TActions - An object type where keys are action names and values are objects
35
+ * defining the endpoint, method, and types for that action.
36
+ * @param axiosInstance - The configured Axios instance from `createApiClient`.
37
+ * @param actionsConfig - An object defining the configuration for each custom action.
38
+ * @returns A fully-typed object of executable API action functions.
39
+ *
40
+ * @example
41
+ * const authActions = createApiActions(apiClient, {
42
+ * login: { method: 'POST', endpoint: '/auth/login', requestType: {} as LoginCredentials, responseType: {} as AuthResponse },
43
+ * getProfile: { method: 'GET', endpoint: '/user/profile', requestType: {} as void, responseType: {} as UserProfile }
44
+ * });
45
+ *
46
+ * // Usage:
47
+ * const result = await authActions.login({ email: '..', password: '..' });
48
+ */
49
+ declare function createApiActions<TActions extends Record<string, {
50
+ method: Method;
51
+ endpoint: string;
52
+ requestType: any;
53
+ responseType: any;
54
+ log?: boolean;
55
+ }>>(axiosInstance: AxiosInstance, actionsConfig: TActions): {
56
+ [K in keyof TActions]: ApiAction<TActions[K]['requestType'], TActions[K]['responseType']>;
57
+ };
58
+
59
+ declare class GlobalStateManager {
60
+ private store;
61
+ getSnapshot<T>(key: string): ActionStateModule<T>;
62
+ /**
63
+ * يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
64
+ * @returns دالة لإلغاء الاشتراك.
65
+ */
66
+ subscribe(key: string, callback: () => void): () => void;
67
+ /**
68
+ * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
69
+ */
70
+ setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
71
+ /**
72
+ * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
73
+ */
74
+ invalidate(key: string): void;
75
+ /**
76
+ * [نسخة محدثة وأكثر قوة]
77
+ * يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
78
+ * @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
79
+ */
80
+ invalidateByPrefix(prefix: string): void;
81
+ /**
82
+ * Serializes the current state of the query store into a JSON string.
83
+ * This is used on the server to pass the initial state to the client.
84
+ * @returns A JSON string representing the dehydrated state.
85
+ */
86
+ dehydrate(): string;
87
+ /**
88
+ * Merges a dehydrated state object into the current store.
89
+ * This is used on the client to hydrate the state received from the server.
90
+ * @param hydratedState - A JSON string from the `dehydrate` method.
91
+ */
92
+ rehydrate(hydratedState: string): void;
93
+ }
94
+ declare const globalStateManager: GlobalStateManager;
95
+
96
+ /**
97
+ * [نسخة مطورة] يبني سلسلة استعلام (query string) من كائن الخيارات.
98
+ * يدعم الآن الفلاتر المتداخلة (filter[key]=value) والترتيب المتعدد.
99
+ * @param options - كائن خيارات الاستعلام (فلترة, ترتيب, ...).
100
+ * @returns سلسلة استعلام جاهزة للإضافة للرابط.
101
+ */
102
+ declare function buildPaginateQuery(options: QueryOptions): string;
103
+
104
+ /**
105
+ * [النسخة النهائية والمضمونة]
106
+ * تستخدم دوال حماية النوع المخصصة للقضاء على أخطاء 'never' بشكل نهائي.
107
+ */
108
+ declare const processResponse: <T>(responseOrError: AxiosResponse<any> | AxiosError) => StandardResponse<T>;
109
+
110
+ interface CacheItem<T> {
111
+ data: T;
112
+ timestamp: number;
113
+ duration: number;
114
+ }
115
+ declare class CacheManager {
116
+ private cache;
117
+ private defaultDuration;
118
+ set<T>(key: string, data: T, duration?: number): void;
119
+ get<T>(key: string): T | null;
120
+ /**
121
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
122
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
123
+ */
124
+ getWithMeta<T>(key: string): CacheItem<T> | null;
125
+ delete(key: string): void;
126
+ clear(): void;
127
+ invalidateByPrefix(prefix: string): void;
128
+ }
129
+ declare const cacheManager: CacheManager;
130
+
131
+ /**
132
+ * يقوم بإنشاء مفتاح تخزين مؤقت فريد وثابت لإجراء معين ومدخلاته.
133
+ * هذا يضمن أن نفس الطلب ينتج دائمًا نفس المفتاح.
134
+ * @param moduleName - عادةً ما يكون `baseEndpoint` للموديول.
135
+ * @param actionName - اسم الإجراء (مثل 'list', 'create').
136
+ * @param input - بيانات الطلب (body/query params).
137
+ * @param callOptions - خيارات إضافية مثل `pathParams`.
138
+ * @returns سلسلة نصية فريدة تمثل مفتاح التخزين المؤقت.
139
+ */
140
+ declare const generateCacheKey: (moduleName: string, actionName: string, input?: unknown, callOptions?: {
141
+ pathParams?: Record<string, any>;
142
+ }) => string;
143
+
144
+ /**
145
+ * @file src/hooks/useApi.types.ts
146
+ * @description This file defines the professional, publicly-facing types for the `useApi` hook,
147
+ * providing a clean and stable contract for consumers.
148
+ */
149
+
150
+ /**
151
+ * Configuration object for the `useApi` hook.
152
+ * @template T The type of the data entity.
153
+ */
154
+ /**
155
+ * A collection of callable functions for performing CRUD and other operations.
156
+ * These actions automatically handle state updates like loading and refetching.
157
+ * @template T The type of the data entity being managed.
158
+ */
159
+ interface UseApiActions<T, TListItem = T extends (infer U)[] ? U : T> {
160
+ fetch: (querryOptions?: QueryOptions) => Promise<void>;
161
+ create: (newItem: Partial<TListItem>, options?: ActionOptions) => Promise<StandardResponse<TListItem>>;
162
+ put: (id: string | number, item: TListItem, options?: ActionOptions) => Promise<StandardResponse<TListItem>>;
163
+ update: (id: string | number, updatedItem: Partial<TListItem>, options?: ActionOptions) => Promise<StandardResponse<TListItem>>;
164
+ remove: (id: string | number, options?: ActionOptions) => Promise<StandardResponse<any>>;
165
+ bulkRemove: (ids: Array<string | number>, options?: ActionOptions) => Promise<StandardResponse<any>>;
166
+ }
167
+ /**
168
+ * The complete return type of the `useApi` hook.
169
+ * It encapsulates the state, actions, and query controls for a given API resource.
170
+ * @template T The type of the data entity being managed.
171
+ */
172
+ interface UseApiReturn<T> {
173
+ state: StandardResponse<T>;
174
+ setState: React.Dispatch<React.SetStateAction<StandardResponse<T>>>;
175
+ actions: UseApiActions<T>;
176
+ query: UseApiQuery;
177
+ }
178
+
179
+ type ApiResourceStatus = 'idle' | 'loading' | 'success' | 'error';
180
+ interface UseApiResourceState<T> {
181
+ data: T | T[] | null;
182
+ error: ApiError | null;
183
+ status: ApiResourceStatus;
184
+ isFetching: boolean;
185
+ isMutating: boolean;
186
+ isSuccess: boolean;
187
+ lastResponse?: StandardResponse<any>;
188
+ }
189
+ interface UseApiResourceActions<T, TCreate, TUpdate, TPathParams> {
190
+ fetch: (pathParams?: TPathParams, queryOptions?: QueryOptions) => Promise<StandardResponse<T[]>>;
191
+ fetchOne: (pathParams: TPathParams & {
192
+ id: string | number;
193
+ }, queryOptions?: QueryOptions) => Promise<StandardResponse<T>>;
194
+ create: (newItem: TCreate, pathParams?: TPathParams, options?: ActionOptions) => Promise<StandardResponse<T>>;
195
+ update: (id: string | number, updatedItem: TUpdate, pathParams?: TPathParams, options?: ActionOptions) => Promise<StandardResponse<T>>;
196
+ remove: (id: string | number, pathParams?: TPathParams, options?: ActionOptions) => Promise<StandardResponse<any>>;
197
+ reset: () => void;
198
+ }
199
+ interface UseApiResourceConfig<TPathParams> {
200
+ /**
201
+ * The API endpoint template. Can be a static string or a function
202
+ * that builds the URL from parameters.
203
+ * @example '/users'
204
+ * @example (params) => `/modules/${params.moduleName}/records`
205
+ */
206
+ endpoint: string | ((params: TPathParams) => string);
207
+ /** Initial data to populate the state. */
208
+ initialData?: any;
209
+ /** Controls the verbosity of console logs for debugging. */
210
+ logLevel?: LogLevel;
211
+ /** Unique identifier for this hook instance, used in logging. */
212
+ logKey?: string;
213
+ /** Callback for success */
214
+ onSuccess?: (message: string, data?: any) => void;
215
+ /** Callback for error */
216
+ onError?: (message: string, error?: ApiError) => void;
217
+ }
218
+ interface UseApiResourceReturn<T, TCreate, TUpdate, TPathParams> {
219
+ state: UseApiResourceState<T>;
220
+ actions: UseApiResourceActions<T, TCreate, TUpdate, TPathParams>;
221
+ query: UseApiQuery;
222
+ setQuery: React.Dispatch<React.SetStateAction<QueryOptions>>;
223
+ }
224
+
225
+ export { ActionConfigModule, ActionOptions, ActionStateModule, ApiClientConfig, ApiError, type ApiResourceStatus, LogLevel, QueryOptions, RequestConfig, StandardResponse, type UseApiActions, UseApiQuery, type UseApiResourceActions, type UseApiResourceConfig, type UseApiResourceReturn, type UseApiResourceState, type UseApiReturn, buildPaginateQuery, cacheManager, callDynamicApi, createApiActions, createApiClient, createApiServices, generateCacheKey, globalStateManager, processResponse };