api-core-lib 3.3.2 → 3.3.3

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.d.mts CHANGED
@@ -75,19 +75,6 @@ interface PaginateQueryOptions {
75
75
  }[];
76
76
  filter?: Record<string, any>;
77
77
  }
78
- /**
79
- * واجهة لتهيئة الهوك `useApi`.
80
- * @template T نوع البيانات التي يتعامل معها الهوك.
81
- */
82
- interface UseApiConfig<T> {
83
- endpoint: string;
84
- initialData?: T | T[];
85
- initialQuery?: PaginateQueryOptions;
86
- enabled?: boolean;
87
- refetchAfterChange?: boolean;
88
- onSuccess?: (message: string, data?: T) => void;
89
- onError?: (message: string, error?: ApiError) => void;
90
- }
91
78
  /**
92
79
  * واجهة لتخصيص عملية تجديد التوكن بشكل كامل.
93
80
  */
@@ -174,6 +161,49 @@ interface StandardResponse<T> {
174
161
  message?: string;
175
162
  validationErrors?: ValidationError[];
176
163
  }
164
+ /**
165
+ * NEW: واجهة استعلام مرنة تسمح بالبارامترات القياسية (للفلترة والترقيم)
166
+ * بالإضافة إلى أي بارامترات مخصصة أخرى عبر الـ index signature.
167
+ * @example
168
+ * { page: 1, limit: 10, search: 'term', status: 'published', authorId: 123 }
169
+ */
170
+ interface QueryOptions {
171
+ page?: number;
172
+ limit?: number;
173
+ search?: string;
174
+ sortBy?: {
175
+ key: string;
176
+ direction: 'asc' | 'desc';
177
+ }[];
178
+ filter?: Record<string, any>;
179
+ [key: string]: any;
180
+ }
181
+ /**
182
+ * NEW: واجهة لتمرير خيارات إضافية لدوال الأكشن (create, update, remove).
183
+ */
184
+ interface ActionOptions {
185
+ /**
186
+ * يسمح لك بتجاوز الـ endpoint الافتراضي المحدد في الهوك.
187
+ * مفيد لإرسال طلبات لنقاط نهاية متخصصة.
188
+ * @example
189
+ * // لتحديث عنصر وتغيير حالته عبر مسار مختلف
190
+ * update('123', { status: 'active' }, { endpoint: '/items/123/activate' })
191
+ */
192
+ endpoint?: string;
193
+ }
194
+ /**
195
+ * واجهة لتهيئة الهوك `useApi`.
196
+ * @template T نوع البيانات التي يتعامل معها الهوك.
197
+ */
198
+ interface UseApiConfig<T> {
199
+ endpoint: string;
200
+ initialData?: T | T[];
201
+ initialQuery?: QueryOptions;
202
+ enabled?: boolean;
203
+ refetchAfterChange?: boolean;
204
+ onSuccess?: (message: string, data?: T) => void;
205
+ onError?: (message: string, error?: ApiError) => void;
206
+ }
177
207
 
178
208
  /**
179
209
  * @file src/core/client.ts
@@ -185,12 +215,13 @@ interface StandardResponse<T> {
185
215
 
186
216
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
187
217
 
218
+ type CrudRequestConfig = RequestConfig & ActionOptions;
188
219
  declare function createApiServices<T>(axiosInstance: AxiosInstance, endpoint: string): {
189
220
  get: (id?: string, config?: RequestConfig) => Promise<StandardResponse<T | T[]>>;
190
221
  getWithQuery: (query: string, config?: RequestConfig) => Promise<StandardResponse<T[]>>;
191
- post: (data: Partial<T>, config?: RequestConfig) => Promise<StandardResponse<T>>;
192
- patch: (id: string, data: Partial<T>, config?: RequestConfig) => Promise<StandardResponse<T>>;
193
- remove: (id: string, config?: RequestConfig) => Promise<StandardResponse<any>>;
222
+ post: (data: Partial<T>, config?: CrudRequestConfig) => Promise<StandardResponse<T>>;
223
+ patch: (id: string, data: Partial<T>, config?: CrudRequestConfig) => Promise<StandardResponse<T>>;
224
+ remove: (id: string, config?: CrudRequestConfig) => Promise<StandardResponse<any>>;
194
225
  };
195
226
 
196
227
  /**
@@ -201,7 +232,13 @@ declare function createApiServices<T>(axiosInstance: AxiosInstance, endpoint: st
201
232
  * بالإضافة إلى دوال التحقق من الأنواع (type guards).
202
233
  */
203
234
 
204
- declare function buildPaginateQuery(query: PaginateQueryOptions): string;
235
+ /**
236
+ * يبني سلسلة استعلام (query string) من كائن خيارات مرن.
237
+ * يتعامل مع البارامترات القياسية والمخصصة.
238
+ * @param query - كائن من نوع QueryOptions.
239
+ * @returns سلسلة استعلام جاهزة للإضافة للرابط.
240
+ */
241
+ declare function buildPaginateQuery(query: QueryOptions): string;
205
242
 
206
243
  /**
207
244
  * Defines a single custom API action.
@@ -263,14 +300,14 @@ declare function useApi<T extends {
263
300
  state: StandardResponse<T | T[]>;
264
301
  setState: react.Dispatch<react.SetStateAction<StandardResponse<T | T[]>>>;
265
302
  actions: {
266
- fetch: () => Promise<void>;
267
- create: (newItem: Partial<T>) => Promise<StandardResponse<T>>;
268
- update: (id: string, updatedItem: Partial<T>) => Promise<StandardResponse<T>>;
269
- remove: (id: string) => Promise<StandardResponse<any>>;
303
+ fetch: (options?: QueryOptions) => Promise<void>;
304
+ create: (newItem: Partial<T>, options?: ActionOptions) => Promise<StandardResponse<T>>;
305
+ update: (id: string, updatedItem: Partial<T>, options?: ActionOptions) => Promise<StandardResponse<T>>;
306
+ remove: (id: string, options?: ActionOptions) => Promise<StandardResponse<any>>;
270
307
  };
271
308
  query: {
272
- options: PaginateQueryOptions;
273
- setOptions: react.Dispatch<react.SetStateAction<PaginateQueryOptions>>;
309
+ options: QueryOptions;
310
+ setOptions: react.Dispatch<react.SetStateAction<QueryOptions>>;
274
311
  setPage: (page: number) => void;
275
312
  setLimit: (limit: number) => void;
276
313
  setSearchTerm: (search: string) => void;
@@ -279,8 +316,9 @@ declare function useApi<T extends {
279
316
  direction: "asc" | "desc";
280
317
  }[]) => void;
281
318
  setFilters: (filter: Record<string, any>) => void;
319
+ setQueryParam: (key: string, value: any) => void;
282
320
  reset: () => void;
283
321
  };
284
322
  };
285
323
 
286
- export { type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
324
+ export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
package/dist/index.d.ts CHANGED
@@ -75,19 +75,6 @@ interface PaginateQueryOptions {
75
75
  }[];
76
76
  filter?: Record<string, any>;
77
77
  }
78
- /**
79
- * واجهة لتهيئة الهوك `useApi`.
80
- * @template T نوع البيانات التي يتعامل معها الهوك.
81
- */
82
- interface UseApiConfig<T> {
83
- endpoint: string;
84
- initialData?: T | T[];
85
- initialQuery?: PaginateQueryOptions;
86
- enabled?: boolean;
87
- refetchAfterChange?: boolean;
88
- onSuccess?: (message: string, data?: T) => void;
89
- onError?: (message: string, error?: ApiError) => void;
90
- }
91
78
  /**
92
79
  * واجهة لتخصيص عملية تجديد التوكن بشكل كامل.
93
80
  */
@@ -174,6 +161,49 @@ interface StandardResponse<T> {
174
161
  message?: string;
175
162
  validationErrors?: ValidationError[];
176
163
  }
164
+ /**
165
+ * NEW: واجهة استعلام مرنة تسمح بالبارامترات القياسية (للفلترة والترقيم)
166
+ * بالإضافة إلى أي بارامترات مخصصة أخرى عبر الـ index signature.
167
+ * @example
168
+ * { page: 1, limit: 10, search: 'term', status: 'published', authorId: 123 }
169
+ */
170
+ interface QueryOptions {
171
+ page?: number;
172
+ limit?: number;
173
+ search?: string;
174
+ sortBy?: {
175
+ key: string;
176
+ direction: 'asc' | 'desc';
177
+ }[];
178
+ filter?: Record<string, any>;
179
+ [key: string]: any;
180
+ }
181
+ /**
182
+ * NEW: واجهة لتمرير خيارات إضافية لدوال الأكشن (create, update, remove).
183
+ */
184
+ interface ActionOptions {
185
+ /**
186
+ * يسمح لك بتجاوز الـ endpoint الافتراضي المحدد في الهوك.
187
+ * مفيد لإرسال طلبات لنقاط نهاية متخصصة.
188
+ * @example
189
+ * // لتحديث عنصر وتغيير حالته عبر مسار مختلف
190
+ * update('123', { status: 'active' }, { endpoint: '/items/123/activate' })
191
+ */
192
+ endpoint?: string;
193
+ }
194
+ /**
195
+ * واجهة لتهيئة الهوك `useApi`.
196
+ * @template T نوع البيانات التي يتعامل معها الهوك.
197
+ */
198
+ interface UseApiConfig<T> {
199
+ endpoint: string;
200
+ initialData?: T | T[];
201
+ initialQuery?: QueryOptions;
202
+ enabled?: boolean;
203
+ refetchAfterChange?: boolean;
204
+ onSuccess?: (message: string, data?: T) => void;
205
+ onError?: (message: string, error?: ApiError) => void;
206
+ }
177
207
 
178
208
  /**
179
209
  * @file src/core/client.ts
@@ -185,12 +215,13 @@ interface StandardResponse<T> {
185
215
 
186
216
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
187
217
 
218
+ type CrudRequestConfig = RequestConfig & ActionOptions;
188
219
  declare function createApiServices<T>(axiosInstance: AxiosInstance, endpoint: string): {
189
220
  get: (id?: string, config?: RequestConfig) => Promise<StandardResponse<T | T[]>>;
190
221
  getWithQuery: (query: string, config?: RequestConfig) => Promise<StandardResponse<T[]>>;
191
- post: (data: Partial<T>, config?: RequestConfig) => Promise<StandardResponse<T>>;
192
- patch: (id: string, data: Partial<T>, config?: RequestConfig) => Promise<StandardResponse<T>>;
193
- remove: (id: string, config?: RequestConfig) => Promise<StandardResponse<any>>;
222
+ post: (data: Partial<T>, config?: CrudRequestConfig) => Promise<StandardResponse<T>>;
223
+ patch: (id: string, data: Partial<T>, config?: CrudRequestConfig) => Promise<StandardResponse<T>>;
224
+ remove: (id: string, config?: CrudRequestConfig) => Promise<StandardResponse<any>>;
194
225
  };
195
226
 
196
227
  /**
@@ -201,7 +232,13 @@ declare function createApiServices<T>(axiosInstance: AxiosInstance, endpoint: st
201
232
  * بالإضافة إلى دوال التحقق من الأنواع (type guards).
202
233
  */
203
234
 
204
- declare function buildPaginateQuery(query: PaginateQueryOptions): string;
235
+ /**
236
+ * يبني سلسلة استعلام (query string) من كائن خيارات مرن.
237
+ * يتعامل مع البارامترات القياسية والمخصصة.
238
+ * @param query - كائن من نوع QueryOptions.
239
+ * @returns سلسلة استعلام جاهزة للإضافة للرابط.
240
+ */
241
+ declare function buildPaginateQuery(query: QueryOptions): string;
205
242
 
206
243
  /**
207
244
  * Defines a single custom API action.
@@ -263,14 +300,14 @@ declare function useApi<T extends {
263
300
  state: StandardResponse<T | T[]>;
264
301
  setState: react.Dispatch<react.SetStateAction<StandardResponse<T | T[]>>>;
265
302
  actions: {
266
- fetch: () => Promise<void>;
267
- create: (newItem: Partial<T>) => Promise<StandardResponse<T>>;
268
- update: (id: string, updatedItem: Partial<T>) => Promise<StandardResponse<T>>;
269
- remove: (id: string) => Promise<StandardResponse<any>>;
303
+ fetch: (options?: QueryOptions) => Promise<void>;
304
+ create: (newItem: Partial<T>, options?: ActionOptions) => Promise<StandardResponse<T>>;
305
+ update: (id: string, updatedItem: Partial<T>, options?: ActionOptions) => Promise<StandardResponse<T>>;
306
+ remove: (id: string, options?: ActionOptions) => Promise<StandardResponse<any>>;
270
307
  };
271
308
  query: {
272
- options: PaginateQueryOptions;
273
- setOptions: react.Dispatch<react.SetStateAction<PaginateQueryOptions>>;
309
+ options: QueryOptions;
310
+ setOptions: react.Dispatch<react.SetStateAction<QueryOptions>>;
274
311
  setPage: (page: number) => void;
275
312
  setLimit: (limit: number) => void;
276
313
  setSearchTerm: (search: string) => void;
@@ -279,8 +316,9 @@ declare function useApi<T extends {
279
316
  direction: "asc" | "desc";
280
317
  }[]) => void;
281
318
  setFilters: (filter: Record<string, any>) => void;
319
+ setQueryParam: (key: string, value: any) => void;
282
320
  reset: () => void;
283
321
  };
284
322
  };
285
323
 
286
- export { type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
324
+ export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
package/dist/index.js CHANGED
@@ -164,6 +164,7 @@ var import_axios2 = __toESM(require("axios"));
164
164
  function buildPaginateQuery(query) {
165
165
  if (!query) return "";
166
166
  const params = new URLSearchParams();
167
+ const standardKeys = /* @__PURE__ */ new Set(["page", "limit", "search", "sortBy", "filter"]);
167
168
  if (query.page) params.append("page", query.page.toString());
168
169
  if (query.limit) params.append("limit", query.limit.toString());
169
170
  if (query.search) params.append("search", query.search);
@@ -175,6 +176,14 @@ function buildPaginateQuery(query) {
175
176
  params.append(`filter.${field}`, String(value));
176
177
  });
177
178
  }
179
+ for (const key in query) {
180
+ if (Object.prototype.hasOwnProperty.call(query, key) && !standardKeys.has(key)) {
181
+ const value = query[key];
182
+ if (value !== void 0 && value !== null) {
183
+ params.append(key, String(value));
184
+ }
185
+ }
186
+ }
178
187
  const queryString = params.toString();
179
188
  return queryString ? `?${queryString}` : "";
180
189
  }
@@ -244,24 +253,27 @@ function createApiServices(axiosInstance, endpoint) {
244
253
  }
245
254
  };
246
255
  const post = async (data, config) => {
256
+ const finalUrl = config?.endpoint || endpoint;
247
257
  try {
248
- const response = await axiosInstance.post(endpoint, data, config);
258
+ const response = await axiosInstance.post(finalUrl, data, config);
249
259
  return processResponse(response);
250
260
  } catch (error) {
251
261
  return processResponse(error);
252
262
  }
253
263
  };
254
264
  const patch = async (id, data, config) => {
265
+ const finalUrl = config?.endpoint || `${endpoint}/${id}`;
255
266
  try {
256
- const response = await axiosInstance.patch(`${endpoint}/${id}`, data, config);
267
+ const response = await axiosInstance.patch(finalUrl, data, config);
257
268
  return processResponse(response);
258
269
  } catch (error) {
259
270
  return processResponse(error);
260
271
  }
261
272
  };
262
273
  const remove = async (id, config) => {
274
+ const finalUrl = config?.endpoint || `${endpoint}/${id}`;
263
275
  try {
264
- const response = await axiosInstance.delete(`${endpoint}/${id}`, config);
276
+ const response = await axiosInstance.delete(finalUrl, config);
265
277
  return processResponse(response);
266
278
  } catch (error) {
267
279
  return processResponse(error);
@@ -335,15 +347,15 @@ function useApi(axiosInstance, config) {
335
347
  const {
336
348
  endpoint,
337
349
  initialData,
338
- initialQuery = { page: 1, limit: 10 },
350
+ initialQuery = { limit: 10 },
339
351
  enabled = true,
340
352
  refetchAfterChange = true,
353
+ // تم تعديل القيمة الافتراضية لتكون أكثر شيوعًا
341
354
  onSuccess,
342
355
  onError
343
356
  } = config;
344
357
  const [state, setState] = (0, import_react.useState)({
345
358
  data: initialData || null,
346
- // <--- التغيير هنا
347
359
  rawResponse: null,
348
360
  loading: enabled,
349
361
  error: null,
@@ -351,9 +363,10 @@ function useApi(axiosInstance, config) {
351
363
  });
352
364
  const [queryOptions, setQueryOptions] = (0, import_react.useState)(initialQuery);
353
365
  const apiServices = (0, import_react.useRef)(createApiServices(axiosInstance, endpoint)).current;
354
- const fetchData = (0, import_react.useCallback)(async () => {
366
+ const fetchData = (0, import_react.useCallback)(async (options) => {
367
+ const currentQuery = options || queryOptions;
355
368
  setState((prev) => ({ ...prev, data: null, loading: true, error: null }));
356
- const queryString = buildPaginateQuery(queryOptions);
369
+ const queryString = buildPaginateQuery(currentQuery);
357
370
  const result = await apiServices.getWithQuery(queryString, { cancelTokenKey: endpoint });
358
371
  setState(result);
359
372
  if (!result.success && onError) {
@@ -365,9 +378,9 @@ function useApi(axiosInstance, config) {
365
378
  fetchData();
366
379
  }
367
380
  }, [enabled, queryOptions]);
368
- const createItem = async (newItem) => {
381
+ const createItem = async (newItem, options) => {
369
382
  setState((prev) => ({ ...prev, loading: true }));
370
- const result = await apiServices.post(newItem);
383
+ const result = await apiServices.post(newItem, options);
371
384
  if (result.success) {
372
385
  if (refetchAfterChange) await fetchData();
373
386
  else setState((prev) => ({ ...prev, loading: false }));
@@ -378,9 +391,9 @@ function useApi(axiosInstance, config) {
378
391
  }
379
392
  return result;
380
393
  };
381
- const updateItem = async (id, updatedItem) => {
394
+ const updateItem = async (id, updatedItem, options) => {
382
395
  setState((prev) => ({ ...prev, loading: true }));
383
- const result = await apiServices.patch(id, updatedItem);
396
+ const result = await apiServices.patch(id, updatedItem, options);
384
397
  if (result.success) {
385
398
  if (refetchAfterChange) await fetchData();
386
399
  else setState((prev) => ({ ...prev, loading: false }));
@@ -391,9 +404,9 @@ function useApi(axiosInstance, config) {
391
404
  }
392
405
  return result;
393
406
  };
394
- const deleteItem = async (id) => {
407
+ const deleteItem = async (id, options) => {
395
408
  setState((prev) => ({ ...prev, loading: true }));
396
- const result = await apiServices.remove(id);
409
+ const result = await apiServices.remove(id, options);
397
410
  if (result.success) {
398
411
  if (refetchAfterChange) await fetchData();
399
412
  else setState((prev) => ({ ...prev, loading: false }));
@@ -409,11 +422,19 @@ function useApi(axiosInstance, config) {
409
422
  const setSearchTerm = (search) => setQueryOptions((prev) => ({ ...prev, search, page: 1 }));
410
423
  const setSorting = (sortBy) => setQueryOptions((prev) => ({ ...prev, sortBy }));
411
424
  const setFilters = (filter) => setQueryOptions((prev) => ({ ...prev, filter, page: 1 }));
425
+ const setQueryParam = (key, value) => {
426
+ setQueryOptions((prev) => {
427
+ const newQuery = { ...prev, [key]: value };
428
+ if (key !== "page") {
429
+ newQuery.page = 1;
430
+ }
431
+ return newQuery;
432
+ });
433
+ };
412
434
  const resetQuery = () => setQueryOptions(initialQuery);
413
435
  return {
414
436
  state,
415
437
  setState,
416
- // Exposing setState for direct manipulation or connection to Redux
417
438
  actions: {
418
439
  fetch: fetchData,
419
440
  create: createItem,
@@ -428,6 +449,8 @@ function useApi(axiosInstance, config) {
428
449
  setSearchTerm,
429
450
  setSorting,
430
451
  setFilters,
452
+ setQueryParam,
453
+ // <-- NEW
431
454
  reset: resetQuery
432
455
  }
433
456
  };
package/dist/index.mjs CHANGED
@@ -122,6 +122,7 @@ import axios2 from "axios";
122
122
  function buildPaginateQuery(query) {
123
123
  if (!query) return "";
124
124
  const params = new URLSearchParams();
125
+ const standardKeys = /* @__PURE__ */ new Set(["page", "limit", "search", "sortBy", "filter"]);
125
126
  if (query.page) params.append("page", query.page.toString());
126
127
  if (query.limit) params.append("limit", query.limit.toString());
127
128
  if (query.search) params.append("search", query.search);
@@ -133,6 +134,14 @@ function buildPaginateQuery(query) {
133
134
  params.append(`filter.${field}`, String(value));
134
135
  });
135
136
  }
137
+ for (const key in query) {
138
+ if (Object.prototype.hasOwnProperty.call(query, key) && !standardKeys.has(key)) {
139
+ const value = query[key];
140
+ if (value !== void 0 && value !== null) {
141
+ params.append(key, String(value));
142
+ }
143
+ }
144
+ }
136
145
  const queryString = params.toString();
137
146
  return queryString ? `?${queryString}` : "";
138
147
  }
@@ -202,24 +211,27 @@ function createApiServices(axiosInstance, endpoint) {
202
211
  }
203
212
  };
204
213
  const post = async (data, config) => {
214
+ const finalUrl = config?.endpoint || endpoint;
205
215
  try {
206
- const response = await axiosInstance.post(endpoint, data, config);
216
+ const response = await axiosInstance.post(finalUrl, data, config);
207
217
  return processResponse(response);
208
218
  } catch (error) {
209
219
  return processResponse(error);
210
220
  }
211
221
  };
212
222
  const patch = async (id, data, config) => {
223
+ const finalUrl = config?.endpoint || `${endpoint}/${id}`;
213
224
  try {
214
- const response = await axiosInstance.patch(`${endpoint}/${id}`, data, config);
225
+ const response = await axiosInstance.patch(finalUrl, data, config);
215
226
  return processResponse(response);
216
227
  } catch (error) {
217
228
  return processResponse(error);
218
229
  }
219
230
  };
220
231
  const remove = async (id, config) => {
232
+ const finalUrl = config?.endpoint || `${endpoint}/${id}`;
221
233
  try {
222
- const response = await axiosInstance.delete(`${endpoint}/${id}`, config);
234
+ const response = await axiosInstance.delete(finalUrl, config);
223
235
  return processResponse(response);
224
236
  } catch (error) {
225
237
  return processResponse(error);
@@ -293,15 +305,15 @@ function useApi(axiosInstance, config) {
293
305
  const {
294
306
  endpoint,
295
307
  initialData,
296
- initialQuery = { page: 1, limit: 10 },
308
+ initialQuery = { limit: 10 },
297
309
  enabled = true,
298
310
  refetchAfterChange = true,
311
+ // تم تعديل القيمة الافتراضية لتكون أكثر شيوعًا
299
312
  onSuccess,
300
313
  onError
301
314
  } = config;
302
315
  const [state, setState] = useState({
303
316
  data: initialData || null,
304
- // <--- التغيير هنا
305
317
  rawResponse: null,
306
318
  loading: enabled,
307
319
  error: null,
@@ -309,9 +321,10 @@ function useApi(axiosInstance, config) {
309
321
  });
310
322
  const [queryOptions, setQueryOptions] = useState(initialQuery);
311
323
  const apiServices = useRef(createApiServices(axiosInstance, endpoint)).current;
312
- const fetchData = useCallback(async () => {
324
+ const fetchData = useCallback(async (options) => {
325
+ const currentQuery = options || queryOptions;
313
326
  setState((prev) => ({ ...prev, data: null, loading: true, error: null }));
314
- const queryString = buildPaginateQuery(queryOptions);
327
+ const queryString = buildPaginateQuery(currentQuery);
315
328
  const result = await apiServices.getWithQuery(queryString, { cancelTokenKey: endpoint });
316
329
  setState(result);
317
330
  if (!result.success && onError) {
@@ -323,9 +336,9 @@ function useApi(axiosInstance, config) {
323
336
  fetchData();
324
337
  }
325
338
  }, [enabled, queryOptions]);
326
- const createItem = async (newItem) => {
339
+ const createItem = async (newItem, options) => {
327
340
  setState((prev) => ({ ...prev, loading: true }));
328
- const result = await apiServices.post(newItem);
341
+ const result = await apiServices.post(newItem, options);
329
342
  if (result.success) {
330
343
  if (refetchAfterChange) await fetchData();
331
344
  else setState((prev) => ({ ...prev, loading: false }));
@@ -336,9 +349,9 @@ function useApi(axiosInstance, config) {
336
349
  }
337
350
  return result;
338
351
  };
339
- const updateItem = async (id, updatedItem) => {
352
+ const updateItem = async (id, updatedItem, options) => {
340
353
  setState((prev) => ({ ...prev, loading: true }));
341
- const result = await apiServices.patch(id, updatedItem);
354
+ const result = await apiServices.patch(id, updatedItem, options);
342
355
  if (result.success) {
343
356
  if (refetchAfterChange) await fetchData();
344
357
  else setState((prev) => ({ ...prev, loading: false }));
@@ -349,9 +362,9 @@ function useApi(axiosInstance, config) {
349
362
  }
350
363
  return result;
351
364
  };
352
- const deleteItem = async (id) => {
365
+ const deleteItem = async (id, options) => {
353
366
  setState((prev) => ({ ...prev, loading: true }));
354
- const result = await apiServices.remove(id);
367
+ const result = await apiServices.remove(id, options);
355
368
  if (result.success) {
356
369
  if (refetchAfterChange) await fetchData();
357
370
  else setState((prev) => ({ ...prev, loading: false }));
@@ -367,11 +380,19 @@ function useApi(axiosInstance, config) {
367
380
  const setSearchTerm = (search) => setQueryOptions((prev) => ({ ...prev, search, page: 1 }));
368
381
  const setSorting = (sortBy) => setQueryOptions((prev) => ({ ...prev, sortBy }));
369
382
  const setFilters = (filter) => setQueryOptions((prev) => ({ ...prev, filter, page: 1 }));
383
+ const setQueryParam = (key, value) => {
384
+ setQueryOptions((prev) => {
385
+ const newQuery = { ...prev, [key]: value };
386
+ if (key !== "page") {
387
+ newQuery.page = 1;
388
+ }
389
+ return newQuery;
390
+ });
391
+ };
370
392
  const resetQuery = () => setQueryOptions(initialQuery);
371
393
  return {
372
394
  state,
373
395
  setState,
374
- // Exposing setState for direct manipulation or connection to Redux
375
396
  actions: {
376
397
  fetch: fetchData,
377
398
  create: createItem,
@@ -386,6 +407,8 @@ function useApi(axiosInstance, config) {
386
407
  setSearchTerm,
387
408
  setSorting,
388
409
  setFilters,
410
+ setQueryParam,
411
+ // <-- NEW
389
412
  reset: resetQuery
390
413
  }
391
414
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-core-lib",
3
- "version": "3.3.2",
3
+ "version": "3.3.3",
4
4
  "description": "A flexible and powerful API client library for modern web applications.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",