api-core-lib 12.0.15 → 12.0.16

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.
@@ -187,6 +187,10 @@ interface UseApiConfig<T> {
187
187
  onSuccess?: (message: string, data?: T) => void;
188
188
  onError?: (message: string, error?: ApiError) => void;
189
189
  }
190
+ interface t {
191
+ type: string;
192
+ payload?: any;
193
+ }
190
194
 
191
195
  /** @description Extends the base ActionState with an `isStale` flag for automatic refetching. */
192
196
  interface ActionState<TOutput> extends ActionStateModule<TOutput> {
@@ -199,11 +203,16 @@ interface ActionConfigModule<TInput = unknown, TOutput = unknown> {
199
203
  description?: string;
200
204
  hasQuery?: boolean;
201
205
  autoFetch?: boolean;
206
+ cacheResponse?: boolean;
202
207
  invalidates?: string[];
203
208
  _input?: TInput;
204
209
  _output?: TOutput;
205
210
  }
206
211
  /** @description Defines the complete structure of an API module. */
212
+ /**
213
+ * يصف إعدادات موديول API كامل.
214
+ * @template TActions كائن يصف جميع الإجراءات المتاحة في الموديول.
215
+ */
207
216
  interface ApiModuleConfig<TActions extends Record<string, ActionConfigModule<any, any>>> {
208
217
  baseEndpoint: string;
209
218
  actions: TActions;
@@ -254,5 +263,22 @@ interface UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<
254
263
  };
255
264
  dehydrate: () => string;
256
265
  }
266
+ /**
267
+ * يصف دوال `execute` و `reset` لإجراء واحد.
268
+ * هذا النوع عام (generic) ليتناسب مع أنواع الإدخال والإخراج المختلفة لكل إجراء.
269
+ * @template TAction يمثل إعدادات الإجراء الواحد.
270
+ */
271
+ type ActionMethods<TAction extends ActionConfigModule<any, any>> = {
272
+ /**
273
+ * الدالة الأساسية لتنفيذ طلب ה-API.
274
+ */
275
+ execute: <TContext = unknown>(input?: InputOf<TAction>, options?: ExecuteOptions<InputOf<TAction>, OutputOf<TAction>, TContext>) => Promise<StandardResponse<OutputOf<TAction>>>;
276
+ /**
277
+ * دالة لإعادة تعيين حالة إجراء معين في ذاكرة التخزين المؤقت إلى حالته الأولية.
278
+ */
279
+ reset: (input?: InputOf<TAction>, options?: {
280
+ pathParams?: Record<string, any>;
281
+ }) => void;
282
+ };
257
283
 
258
- export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, MiddlewareContext as M, OutputOf as O, PaginationMeta as P, QueryOptions as Q, RequestConfig as R, StandardResponse as S, Tokens as T, UseApiConfig as U, ValidationError as V, ApiModuleConfig as a, UseApiModuleOptions as b, UseApiModuleReturn as c, ApiClientConfig as d, ActionOptions as e, ActionStateModule as f, UseApiQuery as g, ApiError as h, TokenManager as i, Middleware as j, RefreshTokenConfig as k, ActionConfig as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q };
284
+ export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, MiddlewareContext as M, OutputOf as O, PaginationMeta as P, QueryOptions as Q, RequestConfig as R, StandardResponse as S, Tokens as T, UseApiConfig as U, ValidationError as V, ApiModuleConfig as a, UseApiModuleOptions as b, UseApiModuleReturn as c, ApiClientConfig as d, ActionOptions as e, ActionStateModule as f, UseApiQuery as g, ApiError as h, TokenManager as i, Middleware as j, RefreshTokenConfig as k, ActionConfig as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q, ActionMethods as r, t };
@@ -187,6 +187,10 @@ interface UseApiConfig<T> {
187
187
  onSuccess?: (message: string, data?: T) => void;
188
188
  onError?: (message: string, error?: ApiError) => void;
189
189
  }
190
+ interface t {
191
+ type: string;
192
+ payload?: any;
193
+ }
190
194
 
191
195
  /** @description Extends the base ActionState with an `isStale` flag for automatic refetching. */
192
196
  interface ActionState<TOutput> extends ActionStateModule<TOutput> {
@@ -199,11 +203,16 @@ interface ActionConfigModule<TInput = unknown, TOutput = unknown> {
199
203
  description?: string;
200
204
  hasQuery?: boolean;
201
205
  autoFetch?: boolean;
206
+ cacheResponse?: boolean;
202
207
  invalidates?: string[];
203
208
  _input?: TInput;
204
209
  _output?: TOutput;
205
210
  }
206
211
  /** @description Defines the complete structure of an API module. */
212
+ /**
213
+ * يصف إعدادات موديول API كامل.
214
+ * @template TActions كائن يصف جميع الإجراءات المتاحة في الموديول.
215
+ */
207
216
  interface ApiModuleConfig<TActions extends Record<string, ActionConfigModule<any, any>>> {
208
217
  baseEndpoint: string;
209
218
  actions: TActions;
@@ -254,5 +263,22 @@ interface UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<
254
263
  };
255
264
  dehydrate: () => string;
256
265
  }
266
+ /**
267
+ * يصف دوال `execute` و `reset` لإجراء واحد.
268
+ * هذا النوع عام (generic) ليتناسب مع أنواع الإدخال والإخراج المختلفة لكل إجراء.
269
+ * @template TAction يمثل إعدادات الإجراء الواحد.
270
+ */
271
+ type ActionMethods<TAction extends ActionConfigModule<any, any>> = {
272
+ /**
273
+ * الدالة الأساسية لتنفيذ طلب ה-API.
274
+ */
275
+ execute: <TContext = unknown>(input?: InputOf<TAction>, options?: ExecuteOptions<InputOf<TAction>, OutputOf<TAction>, TContext>) => Promise<StandardResponse<OutputOf<TAction>>>;
276
+ /**
277
+ * دالة لإعادة تعيين حالة إجراء معين في ذاكرة التخزين المؤقت إلى حالته الأولية.
278
+ */
279
+ reset: (input?: InputOf<TAction>, options?: {
280
+ pathParams?: Record<string, any>;
281
+ }) => void;
282
+ };
257
283
 
258
- export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, MiddlewareContext as M, OutputOf as O, PaginationMeta as P, QueryOptions as Q, RequestConfig as R, StandardResponse as S, Tokens as T, UseApiConfig as U, ValidationError as V, ApiModuleConfig as a, UseApiModuleOptions as b, UseApiModuleReturn as c, ApiClientConfig as d, ActionOptions as e, ActionStateModule as f, UseApiQuery as g, ApiError as h, TokenManager as i, Middleware as j, RefreshTokenConfig as k, ActionConfig as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q };
284
+ export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, MiddlewareContext as M, OutputOf as O, PaginationMeta as P, QueryOptions as Q, RequestConfig as R, StandardResponse as S, Tokens as T, UseApiConfig as U, ValidationError as V, ApiModuleConfig as a, UseApiModuleOptions as b, UseApiModuleReturn as c, ApiClientConfig as d, ActionOptions as e, ActionStateModule as f, UseApiQuery as g, ApiError as h, TokenManager as i, Middleware as j, RefreshTokenConfig as k, ActionConfig as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q, ActionMethods as r, t };
package/dist/client.cjs CHANGED
@@ -612,14 +612,14 @@ var GlobalStateManager = class {
612
612
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
613
613
  */
614
614
  setState(key, updater) {
615
- const currentState = this.getSnapshot(key);
615
+ const item = this.store.get(key);
616
+ const currentState = item.state;
616
617
  const newState = updater(currentState);
617
- if (!this.store.has(key)) {
618
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
619
- } else {
620
- this.store.get(key).state = newState;
618
+ if (Object.is(currentState, newState)) {
619
+ return;
621
620
  }
622
- this.store.get(key).listeners.forEach((listener) => listener());
621
+ item.state = newState;
622
+ item.listeners.forEach((listener) => listener());
623
623
  }
624
624
  /**
625
625
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
@@ -691,24 +691,40 @@ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
691
691
  // src/hooks/useApiModule/useApiModule.ts
692
692
  var ApiModuleContext = (0, import_react4.createContext)(null);
693
693
  var ApiModuleProvider = ApiModuleContext.Provider;
694
- function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
694
+ var createInitialState2 = () => ({
695
+ data: null,
696
+ lastSuccessAt: void 0,
697
+ meta: [],
698
+ validationErrors: [],
699
+ error: null,
700
+ loading: false,
701
+ success: false,
702
+ called: false,
703
+ isStale: false,
704
+ rawResponse: null
705
+ });
706
+ function useApiActionState(actionConfig, cacheKey, execute, input, enabled) {
695
707
  const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
696
708
  const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
697
709
  const state = (0, import_react4.useSyncExternalStore)(
698
710
  (callback) => globalStateManager.subscribe(cacheKey, callback),
699
711
  getClientSnapshot,
700
- // لقطة العميل
701
712
  getServerSnapshot
702
- // لقطة الخادم
703
713
  );
704
- const input = actionConfig.hasQuery ? state.options : void 0;
714
+ const refetch = (0, import_react4.useCallback)(() => {
715
+ execute(input);
716
+ }, [execute, JSON.stringify(input)]);
717
+ const refetchRef = (0, import_react4.useRef)(refetch);
718
+ (0, import_react4.useEffect)(() => {
719
+ refetchRef.current = refetch;
720
+ }, [refetch]);
705
721
  (0, import_react4.useEffect)(() => {
706
722
  if (enabled && actionConfig.autoFetch && !state.called && !state.loading) {
707
- actionExecutor(input);
723
+ refetchRef.current();
708
724
  } else if (enabled && state.isStale && !state.loading) {
709
- actionExecutor(input);
725
+ refetchRef.current();
710
726
  }
711
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
727
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch]);
712
728
  return state;
713
729
  }
714
730
  function useModuleContext() {
@@ -731,29 +747,62 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
731
747
  globalStateManager.rehydrate(hydratedState);
732
748
  }
733
749
  }, [hydratedState]);
750
+ (0, import_react4.useEffect)(() => {
751
+ savedCallbacks.current = { onSuccess, onError };
752
+ }, [onSuccess, onError]);
753
+ (0, import_react4.useMemo)(() => {
754
+ if (hydratedState) {
755
+ globalStateManager.rehydrate(hydratedState);
756
+ }
757
+ }, [hydratedState]);
734
758
  const actions = (0, import_react4.useMemo)(() => {
735
759
  return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
736
760
  const actionConfig = moduleConfig.actions[actionName];
761
+ const shouldCache = actionConfig.cacheResponse !== false;
737
762
  const execute = async (input, options2 = {}) => {
738
763
  const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
739
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
764
+ const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
740
765
  let mutationContext;
741
766
  try {
742
- if (options2.onMutate) {
767
+ if (options2.onMutate && shouldCache) {
743
768
  mutationContext = await options2.onMutate(input);
744
769
  }
745
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
770
+ if (shouldCache) {
771
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
772
+ }
746
773
  const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
747
774
  pathParams: finalPathParams,
748
775
  body: input,
749
776
  config: options2.config
750
777
  });
751
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...result, loading: false }));
778
+ console.log("[API Result]", result);
779
+ if (shouldCache) {
780
+ globalStateManager.setState(cacheKey, (prev) => ({
781
+ ...prev,
782
+ // احتفظ بالخصائص القديمة مثل 'called'
783
+ loading: false,
784
+ success: result.success,
785
+ // تحديث صريح
786
+ error: result.success ? null : result.error || prev.error,
787
+ // تحديث صريح
788
+ data: result.data,
789
+ // تحديث صريح للبيانات
790
+ meta: result.meta,
791
+ // تحديث صريح
792
+ links: result.links,
793
+ // تحديث صريح
794
+ message: result.message,
795
+ validationErrors: result.validationErrors || [],
796
+ rawResponse: result.rawResponse
797
+ // isStale تم تعيينه إلى false في بداية execute، وسيظل كذلك
798
+ }));
799
+ }
752
800
  if (result.success) {
753
801
  savedCallbacks.current.onSuccess?.(actionName, result.message || "Action successful", result.data);
754
802
  options2.onSuccess?.(result.data, mutationContext);
755
803
  actionConfig.invalidates?.forEach((keyToInvalidate) => {
756
804
  const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
805
+ console.log(`[Invalidating] by prefix: ${prefix}`);
757
806
  globalStateManager.invalidateByPrefix(prefix);
758
807
  });
759
808
  } else {
@@ -762,12 +811,13 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
762
811
  }
763
812
  return result;
764
813
  } catch (error) {
765
- const apiError = { status: 500, message: error.message };
766
- const errorResult = { data: null, error: apiError, loading: false, success: false, rawResponse: error };
767
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...errorResult, loading: false }));
814
+ const apiError = error.response?.data || { status: 500, message: error.message };
815
+ if (shouldCache) {
816
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
817
+ }
768
818
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
769
819
  options2.onError?.(apiError, mutationContext);
770
- return errorResult;
820
+ throw error;
771
821
  } finally {
772
822
  if (options2.onSettled) {
773
823
  options2.onSettled();
@@ -775,17 +825,11 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
775
825
  }
776
826
  };
777
827
  const reset = (input, options2 = {}) => {
778
- const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
779
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
780
- globalStateManager.setState(cacheKey, () => ({
781
- data: null,
782
- error: null,
783
- loading: false,
784
- success: false,
785
- called: false,
786
- isStale: false,
787
- rawResponse: null
788
- }));
828
+ if (shouldCache) {
829
+ const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
830
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
831
+ globalStateManager.setState(cacheKey, () => createInitialState2());
832
+ }
789
833
  };
790
834
  acc[actionName] = { execute, reset };
791
835
  return acc;
@@ -817,31 +861,24 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
817
861
  for (const actionName in moduleConfig.actions) {
818
862
  if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
819
863
  const actionConfig = moduleConfig.actions[actionName];
820
- const query = queries[actionName]?.options;
821
- const input = actionConfig.hasQuery ? query : void 0;
822
- const pathParams = JSON.parse(pathParamsString);
823
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
824
- states[actionName] = useApiActionState(
825
- actionConfig,
826
- cacheKey,
827
- actions[actionName].execute,
828
- enabled
829
- );
830
- }
831
- }
832
- (0, import_react4.useEffect)(() => {
833
- if (!enabled) return;
834
- const actionKeys = Object.keys(moduleConfig.actions);
835
- for (const actionName of actionKeys) {
836
- const state = states[actionName];
837
- const actionConfig = moduleConfig.actions[actionName];
838
- if (actionConfig.autoFetch && state && !state.called && !state.loading) {
864
+ if (actionConfig.cacheResponse !== false) {
839
865
  const query = queries[actionName]?.options;
840
866
  const input = actionConfig.hasQuery ? query : void 0;
841
- actions[actionName].execute(input);
867
+ const pathParams = JSON.parse(pathParamsString);
868
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
869
+ states[actionName] = useApiActionState(
870
+ actionConfig,
871
+ cacheKey,
872
+ // [تصحيح] مرر `execute` مباشرة
873
+ actions[actionName].execute,
874
+ input,
875
+ enabled
876
+ );
877
+ } else {
878
+ states[actionName] = createInitialState2();
842
879
  }
843
880
  }
844
- }, [enabled, moduleConfig, actions, states, queries]);
881
+ }
845
882
  const lastBlurTimestamp = (0, import_react4.useRef)(Date.now());
846
883
  (0, import_react4.useEffect)(() => {
847
884
  if (!enabled || !refetchOnWindowFocus) return;
package/dist/client.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-BTtRM9wO.cjs';
3
- import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-CBP3Ufvu.cjs';
2
+ import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-D0LSWRW8.cjs';
3
+ import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-DXv1-ly6.cjs';
4
4
  import * as React from 'react';
5
5
 
6
6
  declare function useApi<T>(axiosInstance: AxiosInstance, config: UseApiConfig<T>): any;
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-BTtRM9wO.js';
3
- import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-BsOSJZ5l.js';
2
+ import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-D0LSWRW8.js';
3
+ import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-C7T0gsX_.js';
4
4
  import * as React from 'react';
5
5
 
6
6
  declare function useApi<T>(axiosInstance: AxiosInstance, config: UseApiConfig<T>): any;
package/dist/client.js CHANGED
@@ -527,7 +527,7 @@ function useDeepCompareEffect(callback, dependencies) {
527
527
  }
528
528
 
529
529
  // src/hooks/useApiModule/useApiModule.ts
530
- import { createContext, useContext, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState3, useSyncExternalStore } from "react";
530
+ import { createContext, useCallback as useCallback3, useContext, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState3, useSyncExternalStore } from "react";
531
531
 
532
532
  // src/core/globalStateManager.ts
533
533
  var createInitialState = () => ({
@@ -573,14 +573,14 @@ var GlobalStateManager = class {
573
573
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
574
574
  */
575
575
  setState(key, updater) {
576
- const currentState = this.getSnapshot(key);
576
+ const item = this.store.get(key);
577
+ const currentState = item.state;
577
578
  const newState = updater(currentState);
578
- if (!this.store.has(key)) {
579
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
580
- } else {
581
- this.store.get(key).state = newState;
579
+ if (Object.is(currentState, newState)) {
580
+ return;
582
581
  }
583
- this.store.get(key).listeners.forEach((listener) => listener());
582
+ item.state = newState;
583
+ item.listeners.forEach((listener) => listener());
584
584
  }
585
585
  /**
586
586
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
@@ -652,24 +652,40 @@ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
652
652
  // src/hooks/useApiModule/useApiModule.ts
653
653
  var ApiModuleContext = createContext(null);
654
654
  var ApiModuleProvider = ApiModuleContext.Provider;
655
- function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
655
+ var createInitialState2 = () => ({
656
+ data: null,
657
+ lastSuccessAt: void 0,
658
+ meta: [],
659
+ validationErrors: [],
660
+ error: null,
661
+ loading: false,
662
+ success: false,
663
+ called: false,
664
+ isStale: false,
665
+ rawResponse: null
666
+ });
667
+ function useApiActionState(actionConfig, cacheKey, execute, input, enabled) {
656
668
  const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
657
669
  const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
658
670
  const state = useSyncExternalStore(
659
671
  (callback) => globalStateManager.subscribe(cacheKey, callback),
660
672
  getClientSnapshot,
661
- // لقطة العميل
662
673
  getServerSnapshot
663
- // لقطة الخادم
664
674
  );
665
- const input = actionConfig.hasQuery ? state.options : void 0;
675
+ const refetch = useCallback3(() => {
676
+ execute(input);
677
+ }, [execute, JSON.stringify(input)]);
678
+ const refetchRef = useRef4(refetch);
679
+ useEffect4(() => {
680
+ refetchRef.current = refetch;
681
+ }, [refetch]);
666
682
  useEffect4(() => {
667
683
  if (enabled && actionConfig.autoFetch && !state.called && !state.loading) {
668
- actionExecutor(input);
684
+ refetchRef.current();
669
685
  } else if (enabled && state.isStale && !state.loading) {
670
- actionExecutor(input);
686
+ refetchRef.current();
671
687
  }
672
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
688
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch]);
673
689
  return state;
674
690
  }
675
691
  function useModuleContext() {
@@ -692,29 +708,62 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
692
708
  globalStateManager.rehydrate(hydratedState);
693
709
  }
694
710
  }, [hydratedState]);
711
+ useEffect4(() => {
712
+ savedCallbacks.current = { onSuccess, onError };
713
+ }, [onSuccess, onError]);
714
+ useMemo3(() => {
715
+ if (hydratedState) {
716
+ globalStateManager.rehydrate(hydratedState);
717
+ }
718
+ }, [hydratedState]);
695
719
  const actions = useMemo3(() => {
696
720
  return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
697
721
  const actionConfig = moduleConfig.actions[actionName];
722
+ const shouldCache = actionConfig.cacheResponse !== false;
698
723
  const execute = async (input, options2 = {}) => {
699
724
  const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
700
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
725
+ const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
701
726
  let mutationContext;
702
727
  try {
703
- if (options2.onMutate) {
728
+ if (options2.onMutate && shouldCache) {
704
729
  mutationContext = await options2.onMutate(input);
705
730
  }
706
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
731
+ if (shouldCache) {
732
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
733
+ }
707
734
  const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
708
735
  pathParams: finalPathParams,
709
736
  body: input,
710
737
  config: options2.config
711
738
  });
712
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...result, loading: false }));
739
+ console.log("[API Result]", result);
740
+ if (shouldCache) {
741
+ globalStateManager.setState(cacheKey, (prev) => ({
742
+ ...prev,
743
+ // احتفظ بالخصائص القديمة مثل 'called'
744
+ loading: false,
745
+ success: result.success,
746
+ // تحديث صريح
747
+ error: result.success ? null : result.error || prev.error,
748
+ // تحديث صريح
749
+ data: result.data,
750
+ // تحديث صريح للبيانات
751
+ meta: result.meta,
752
+ // تحديث صريح
753
+ links: result.links,
754
+ // تحديث صريح
755
+ message: result.message,
756
+ validationErrors: result.validationErrors || [],
757
+ rawResponse: result.rawResponse
758
+ // isStale تم تعيينه إلى false في بداية execute، وسيظل كذلك
759
+ }));
760
+ }
713
761
  if (result.success) {
714
762
  savedCallbacks.current.onSuccess?.(actionName, result.message || "Action successful", result.data);
715
763
  options2.onSuccess?.(result.data, mutationContext);
716
764
  actionConfig.invalidates?.forEach((keyToInvalidate) => {
717
765
  const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
766
+ console.log(`[Invalidating] by prefix: ${prefix}`);
718
767
  globalStateManager.invalidateByPrefix(prefix);
719
768
  });
720
769
  } else {
@@ -723,12 +772,13 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
723
772
  }
724
773
  return result;
725
774
  } catch (error) {
726
- const apiError = { status: 500, message: error.message };
727
- const errorResult = { data: null, error: apiError, loading: false, success: false, rawResponse: error };
728
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...errorResult, loading: false }));
775
+ const apiError = error.response?.data || { status: 500, message: error.message };
776
+ if (shouldCache) {
777
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
778
+ }
729
779
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
730
780
  options2.onError?.(apiError, mutationContext);
731
- return errorResult;
781
+ throw error;
732
782
  } finally {
733
783
  if (options2.onSettled) {
734
784
  options2.onSettled();
@@ -736,17 +786,11 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
736
786
  }
737
787
  };
738
788
  const reset = (input, options2 = {}) => {
739
- const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
740
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
741
- globalStateManager.setState(cacheKey, () => ({
742
- data: null,
743
- error: null,
744
- loading: false,
745
- success: false,
746
- called: false,
747
- isStale: false,
748
- rawResponse: null
749
- }));
789
+ if (shouldCache) {
790
+ const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
791
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
792
+ globalStateManager.setState(cacheKey, () => createInitialState2());
793
+ }
750
794
  };
751
795
  acc[actionName] = { execute, reset };
752
796
  return acc;
@@ -778,31 +822,24 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
778
822
  for (const actionName in moduleConfig.actions) {
779
823
  if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
780
824
  const actionConfig = moduleConfig.actions[actionName];
781
- const query = queries[actionName]?.options;
782
- const input = actionConfig.hasQuery ? query : void 0;
783
- const pathParams = JSON.parse(pathParamsString);
784
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
785
- states[actionName] = useApiActionState(
786
- actionConfig,
787
- cacheKey,
788
- actions[actionName].execute,
789
- enabled
790
- );
791
- }
792
- }
793
- useEffect4(() => {
794
- if (!enabled) return;
795
- const actionKeys = Object.keys(moduleConfig.actions);
796
- for (const actionName of actionKeys) {
797
- const state = states[actionName];
798
- const actionConfig = moduleConfig.actions[actionName];
799
- if (actionConfig.autoFetch && state && !state.called && !state.loading) {
825
+ if (actionConfig.cacheResponse !== false) {
800
826
  const query = queries[actionName]?.options;
801
827
  const input = actionConfig.hasQuery ? query : void 0;
802
- actions[actionName].execute(input);
828
+ const pathParams = JSON.parse(pathParamsString);
829
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
830
+ states[actionName] = useApiActionState(
831
+ actionConfig,
832
+ cacheKey,
833
+ // [تصحيح] مرر `execute` مباشرة
834
+ actions[actionName].execute,
835
+ input,
836
+ enabled
837
+ );
838
+ } else {
839
+ states[actionName] = createInitialState2();
803
840
  }
804
841
  }
805
- }, [enabled, moduleConfig, actions, states, queries]);
842
+ }
806
843
  const lastBlurTimestamp = useRef4(Date.now());
807
844
  useEffect4(() => {
808
845
  if (!enabled || !refetchOnWindowFocus) return;
package/dist/index.cjs CHANGED
@@ -570,14 +570,14 @@ var GlobalStateManager = class {
570
570
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
571
571
  */
572
572
  setState(key, updater) {
573
- const currentState = this.getSnapshot(key);
573
+ const item = this.store.get(key);
574
+ const currentState = item.state;
574
575
  const newState = updater(currentState);
575
- if (!this.store.has(key)) {
576
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
577
- } else {
578
- this.store.get(key).state = newState;
576
+ if (Object.is(currentState, newState)) {
577
+ return;
579
578
  }
580
- this.store.get(key).listeners.forEach((listener) => listener());
579
+ item.state = newState;
580
+ item.listeners.forEach((listener) => listener());
581
581
  }
582
582
  /**
583
583
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse, AxiosError } from 'axios';
2
- import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, f as ActionStateModule, Q as QueryOptions, g as UseApiQuery, h as ApiError, L as LogLevel } from './apiModule.types-BTtRM9wO.cjs';
3
- export { l as ActionConfig, n as ActionState, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, j as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, k as RefreshTokenConfig, i as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError } from './apiModule.types-BTtRM9wO.cjs';
4
- export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-CBP3Ufvu.cjs';
2
+ import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, f as ActionStateModule, Q as QueryOptions, g as UseApiQuery, h as ApiError, L as LogLevel } from './apiModule.types-D0LSWRW8.cjs';
3
+ export { l as ActionConfig, r as ActionMethods, n as ActionState, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, j as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, k as RefreshTokenConfig, i as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError, t } from './apiModule.types-D0LSWRW8.cjs';
4
+ export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-DXv1-ly6.cjs';
5
5
  import 'react';
6
6
 
7
7
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse, AxiosError } from 'axios';
2
- import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, f as ActionStateModule, Q as QueryOptions, g as UseApiQuery, h as ApiError, L as LogLevel } from './apiModule.types-BTtRM9wO.js';
3
- export { l as ActionConfig, n as ActionState, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, j as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, k as RefreshTokenConfig, i as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError } from './apiModule.types-BTtRM9wO.js';
4
- export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-BsOSJZ5l.js';
2
+ import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, f as ActionStateModule, Q as QueryOptions, g as UseApiQuery, h as ApiError, L as LogLevel } from './apiModule.types-D0LSWRW8.js';
3
+ export { l as ActionConfig, r as ActionMethods, n as ActionState, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, j as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, k as RefreshTokenConfig, i as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError, t } from './apiModule.types-D0LSWRW8.js';
4
+ export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-C7T0gsX_.js';
5
5
  import 'react';
6
6
 
7
7
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
package/dist/index.js CHANGED
@@ -528,14 +528,14 @@ var GlobalStateManager = class {
528
528
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
529
529
  */
530
530
  setState(key, updater) {
531
- const currentState = this.getSnapshot(key);
531
+ const item = this.store.get(key);
532
+ const currentState = item.state;
532
533
  const newState = updater(currentState);
533
- if (!this.store.has(key)) {
534
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
535
- } else {
536
- this.store.get(key).state = newState;
534
+ if (Object.is(currentState, newState)) {
535
+ return;
537
536
  }
538
- this.store.get(key).listeners.forEach((listener) => listener());
537
+ item.state = newState;
538
+ item.listeners.forEach((listener) => listener());
539
539
  }
540
540
  /**
541
541
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
package/dist/server.cjs CHANGED
@@ -221,14 +221,14 @@ var GlobalStateManager = class {
221
221
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
222
222
  */
223
223
  setState(key, updater) {
224
- const currentState = this.getSnapshot(key);
224
+ const item = this.store.get(key);
225
+ const currentState = item.state;
225
226
  const newState = updater(currentState);
226
- if (!this.store.has(key)) {
227
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
228
- } else {
229
- this.store.get(key).state = newState;
227
+ if (Object.is(currentState, newState)) {
228
+ return;
230
229
  }
231
- this.store.get(key).listeners.forEach((listener) => listener());
230
+ item.state = newState;
231
+ item.listeners.forEach((listener) => listener());
232
232
  }
233
233
  /**
234
234
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
package/dist/server.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-BTtRM9wO.cjs';
2
+ import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-D0LSWRW8.cjs';
3
3
  import 'react';
4
4
 
5
5
  /**
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AxiosInstance } from 'axios';
2
- import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-BTtRM9wO.js';
2
+ import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-D0LSWRW8.js';
3
3
  import 'react';
4
4
 
5
5
  /**
package/dist/server.js CHANGED
@@ -187,14 +187,14 @@ var GlobalStateManager = class {
187
187
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
188
188
  */
189
189
  setState(key, updater) {
190
- const currentState = this.getSnapshot(key);
190
+ const item = this.store.get(key);
191
+ const currentState = item.state;
191
192
  const newState = updater(currentState);
192
- if (!this.store.has(key)) {
193
- this.store.set(key, { state: newState, listeners: /* @__PURE__ */ new Set() });
194
- } else {
195
- this.store.get(key).state = newState;
193
+ if (Object.is(currentState, newState)) {
194
+ return;
196
195
  }
197
- this.store.get(key).listeners.forEach((listener) => listener());
196
+ item.state = newState;
197
+ item.listeners.forEach((listener) => listener());
198
198
  }
199
199
  /**
200
200
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
@@ -1,5 +1,5 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
- import { R as RequestConfig, h as ApiError, S as StandardResponse, e as ActionOptions } from './apiModule.types-BTtRM9wO.js';
2
+ import { R as RequestConfig, h as ApiError, S as StandardResponse, e as ActionOptions } from './apiModule.types-D0LSWRW8.js';
3
3
 
4
4
  /**
5
5
  * Represents the internal state of the `useApiRecord` hook.
@@ -1,5 +1,5 @@
1
1
  import { Dispatch, SetStateAction } from 'react';
2
- import { R as RequestConfig, h as ApiError, S as StandardResponse, e as ActionOptions } from './apiModule.types-BTtRM9wO.cjs';
2
+ import { R as RequestConfig, h as ApiError, S as StandardResponse, e as ActionOptions } from './apiModule.types-D0LSWRW8.cjs';
3
3
 
4
4
  /**
5
5
  * Represents the internal state of the `useApiRecord` hook.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-core-lib",
3
- "version": "12.0.15",
3
+ "version": "12.0.16",
4
4
  "description": "A flexible and powerful API client library for modern web applications.",
5
5
  "type": "module",
6
6