api-core-lib 12.0.15 → 12.0.17

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
@@ -590,7 +590,6 @@ var GlobalStateManager = class {
590
590
  if (!this.store.has(key)) {
591
591
  const initialState = createInitialState();
592
592
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
593
- return initialState;
594
593
  }
595
594
  return this.store.get(key).state;
596
595
  }
@@ -612,14 +611,14 @@ var GlobalStateManager = class {
612
611
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
613
612
  */
614
613
  setState(key, updater) {
615
- const currentState = this.getSnapshot(key);
614
+ const item = this.store.get(key);
615
+ const currentState = item.state;
616
616
  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;
617
+ if (Object.is(currentState, newState)) {
618
+ return;
621
619
  }
622
- this.store.get(key).listeners.forEach((listener) => listener());
620
+ item.state = newState;
621
+ item.listeners.forEach((listener) => listener());
623
622
  }
624
623
  /**
625
624
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
@@ -691,24 +690,40 @@ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
691
690
  // src/hooks/useApiModule/useApiModule.ts
692
691
  var ApiModuleContext = (0, import_react4.createContext)(null);
693
692
  var ApiModuleProvider = ApiModuleContext.Provider;
694
- function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
693
+ var createInitialState2 = () => ({
694
+ data: null,
695
+ lastSuccessAt: void 0,
696
+ meta: [],
697
+ validationErrors: [],
698
+ error: null,
699
+ loading: false,
700
+ success: false,
701
+ called: false,
702
+ isStale: false,
703
+ rawResponse: null
704
+ });
705
+ function useApiActionState(actionConfig, cacheKey, execute, input, enabled) {
695
706
  const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
696
707
  const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
697
708
  const state = (0, import_react4.useSyncExternalStore)(
698
709
  (callback) => globalStateManager.subscribe(cacheKey, callback),
699
710
  getClientSnapshot,
700
- // لقطة العميل
701
711
  getServerSnapshot
702
- // لقطة الخادم
703
712
  );
704
- const input = actionConfig.hasQuery ? state.options : void 0;
713
+ const refetch = (0, import_react4.useCallback)(() => {
714
+ execute(input);
715
+ }, [execute, JSON.stringify(input)]);
716
+ const refetchRef = (0, import_react4.useRef)(refetch);
717
+ (0, import_react4.useEffect)(() => {
718
+ refetchRef.current = refetch;
719
+ }, [refetch]);
705
720
  (0, import_react4.useEffect)(() => {
706
721
  if (enabled && actionConfig.autoFetch && !state.called && !state.loading) {
707
- actionExecutor(input);
722
+ refetchRef.current();
708
723
  } else if (enabled && state.isStale && !state.loading) {
709
- actionExecutor(input);
724
+ refetchRef.current();
710
725
  }
711
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
726
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch]);
712
727
  return state;
713
728
  }
714
729
  function useModuleContext() {
@@ -731,29 +746,62 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
731
746
  globalStateManager.rehydrate(hydratedState);
732
747
  }
733
748
  }, [hydratedState]);
749
+ (0, import_react4.useEffect)(() => {
750
+ savedCallbacks.current = { onSuccess, onError };
751
+ }, [onSuccess, onError]);
752
+ (0, import_react4.useMemo)(() => {
753
+ if (hydratedState) {
754
+ globalStateManager.rehydrate(hydratedState);
755
+ }
756
+ }, [hydratedState]);
734
757
  const actions = (0, import_react4.useMemo)(() => {
735
758
  return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
736
759
  const actionConfig = moduleConfig.actions[actionName];
760
+ const shouldCache = actionConfig.cacheResponse !== false;
737
761
  const execute = async (input, options2 = {}) => {
738
762
  const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
739
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
763
+ const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
740
764
  let mutationContext;
741
765
  try {
742
- if (options2.onMutate) {
766
+ if (options2.onMutate && shouldCache) {
743
767
  mutationContext = await options2.onMutate(input);
744
768
  }
745
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
769
+ if (shouldCache) {
770
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
771
+ }
746
772
  const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
747
773
  pathParams: finalPathParams,
748
774
  body: input,
749
775
  config: options2.config
750
776
  });
751
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...result, loading: false }));
777
+ console.log("[API Result]", result);
778
+ if (shouldCache) {
779
+ globalStateManager.setState(cacheKey, (prev) => ({
780
+ ...prev,
781
+ // احتفظ بالخصائص القديمة مثل 'called'
782
+ loading: false,
783
+ success: result.success,
784
+ // تحديث صريح
785
+ error: result.success ? null : result.error || prev.error,
786
+ // تحديث صريح
787
+ data: result.data,
788
+ // تحديث صريح للبيانات
789
+ meta: result.meta,
790
+ // تحديث صريح
791
+ links: result.links,
792
+ // تحديث صريح
793
+ message: result.message,
794
+ validationErrors: result.validationErrors || [],
795
+ rawResponse: result.rawResponse
796
+ // isStale تم تعيينه إلى false في بداية execute، وسيظل كذلك
797
+ }));
798
+ }
752
799
  if (result.success) {
753
800
  savedCallbacks.current.onSuccess?.(actionName, result.message || "Action successful", result.data);
754
801
  options2.onSuccess?.(result.data, mutationContext);
755
802
  actionConfig.invalidates?.forEach((keyToInvalidate) => {
756
803
  const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
804
+ console.log(`[Invalidating] by prefix: ${prefix}`);
757
805
  globalStateManager.invalidateByPrefix(prefix);
758
806
  });
759
807
  } else {
@@ -762,12 +810,13 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
762
810
  }
763
811
  return result;
764
812
  } 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 }));
813
+ const apiError = error.response?.data || { status: 500, message: error.message };
814
+ if (shouldCache) {
815
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
816
+ }
768
817
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
769
818
  options2.onError?.(apiError, mutationContext);
770
- return errorResult;
819
+ throw error;
771
820
  } finally {
772
821
  if (options2.onSettled) {
773
822
  options2.onSettled();
@@ -775,17 +824,11 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
775
824
  }
776
825
  };
777
826
  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
- }));
827
+ if (shouldCache) {
828
+ const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
829
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
830
+ globalStateManager.setState(cacheKey, () => createInitialState2());
831
+ }
789
832
  };
790
833
  acc[actionName] = { execute, reset };
791
834
  return acc;
@@ -817,31 +860,24 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
817
860
  for (const actionName in moduleConfig.actions) {
818
861
  if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
819
862
  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) {
863
+ if (actionConfig.cacheResponse !== false) {
839
864
  const query = queries[actionName]?.options;
840
865
  const input = actionConfig.hasQuery ? query : void 0;
841
- actions[actionName].execute(input);
866
+ const pathParams = JSON.parse(pathParamsString);
867
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
868
+ states[actionName] = useApiActionState(
869
+ actionConfig,
870
+ cacheKey,
871
+ // [تصحيح] مرر `execute` مباشرة
872
+ actions[actionName].execute,
873
+ input,
874
+ enabled
875
+ );
876
+ } else {
877
+ states[actionName] = createInitialState2();
842
878
  }
843
879
  }
844
- }, [enabled, moduleConfig, actions, states, queries]);
880
+ }
845
881
  const lastBlurTimestamp = (0, import_react4.useRef)(Date.now());
846
882
  (0, import_react4.useEffect)(() => {
847
883
  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 = () => ({
@@ -551,7 +551,6 @@ var GlobalStateManager = class {
551
551
  if (!this.store.has(key)) {
552
552
  const initialState = createInitialState();
553
553
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
554
- return initialState;
555
554
  }
556
555
  return this.store.get(key).state;
557
556
  }
@@ -573,14 +572,14 @@ var GlobalStateManager = class {
573
572
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
574
573
  */
575
574
  setState(key, updater) {
576
- const currentState = this.getSnapshot(key);
575
+ const item = this.store.get(key);
576
+ const currentState = item.state;
577
577
  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;
578
+ if (Object.is(currentState, newState)) {
579
+ return;
582
580
  }
583
- this.store.get(key).listeners.forEach((listener) => listener());
581
+ item.state = newState;
582
+ item.listeners.forEach((listener) => listener());
584
583
  }
585
584
  /**
586
585
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
@@ -652,24 +651,40 @@ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
652
651
  // src/hooks/useApiModule/useApiModule.ts
653
652
  var ApiModuleContext = createContext(null);
654
653
  var ApiModuleProvider = ApiModuleContext.Provider;
655
- function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
654
+ var createInitialState2 = () => ({
655
+ data: null,
656
+ lastSuccessAt: void 0,
657
+ meta: [],
658
+ validationErrors: [],
659
+ error: null,
660
+ loading: false,
661
+ success: false,
662
+ called: false,
663
+ isStale: false,
664
+ rawResponse: null
665
+ });
666
+ function useApiActionState(actionConfig, cacheKey, execute, input, enabled) {
656
667
  const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
657
668
  const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
658
669
  const state = useSyncExternalStore(
659
670
  (callback) => globalStateManager.subscribe(cacheKey, callback),
660
671
  getClientSnapshot,
661
- // لقطة العميل
662
672
  getServerSnapshot
663
- // لقطة الخادم
664
673
  );
665
- const input = actionConfig.hasQuery ? state.options : void 0;
674
+ const refetch = useCallback3(() => {
675
+ execute(input);
676
+ }, [execute, JSON.stringify(input)]);
677
+ const refetchRef = useRef4(refetch);
678
+ useEffect4(() => {
679
+ refetchRef.current = refetch;
680
+ }, [refetch]);
666
681
  useEffect4(() => {
667
682
  if (enabled && actionConfig.autoFetch && !state.called && !state.loading) {
668
- actionExecutor(input);
683
+ refetchRef.current();
669
684
  } else if (enabled && state.isStale && !state.loading) {
670
- actionExecutor(input);
685
+ refetchRef.current();
671
686
  }
672
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
687
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch]);
673
688
  return state;
674
689
  }
675
690
  function useModuleContext() {
@@ -692,29 +707,62 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
692
707
  globalStateManager.rehydrate(hydratedState);
693
708
  }
694
709
  }, [hydratedState]);
710
+ useEffect4(() => {
711
+ savedCallbacks.current = { onSuccess, onError };
712
+ }, [onSuccess, onError]);
713
+ useMemo3(() => {
714
+ if (hydratedState) {
715
+ globalStateManager.rehydrate(hydratedState);
716
+ }
717
+ }, [hydratedState]);
695
718
  const actions = useMemo3(() => {
696
719
  return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
697
720
  const actionConfig = moduleConfig.actions[actionName];
721
+ const shouldCache = actionConfig.cacheResponse !== false;
698
722
  const execute = async (input, options2 = {}) => {
699
723
  const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
700
- const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
724
+ const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
701
725
  let mutationContext;
702
726
  try {
703
- if (options2.onMutate) {
727
+ if (options2.onMutate && shouldCache) {
704
728
  mutationContext = await options2.onMutate(input);
705
729
  }
706
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
730
+ if (shouldCache) {
731
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
732
+ }
707
733
  const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
708
734
  pathParams: finalPathParams,
709
735
  body: input,
710
736
  config: options2.config
711
737
  });
712
- globalStateManager.setState(cacheKey, (prev) => ({ ...prev, ...result, loading: false }));
738
+ console.log("[API Result]", result);
739
+ if (shouldCache) {
740
+ globalStateManager.setState(cacheKey, (prev) => ({
741
+ ...prev,
742
+ // احتفظ بالخصائص القديمة مثل 'called'
743
+ loading: false,
744
+ success: result.success,
745
+ // تحديث صريح
746
+ error: result.success ? null : result.error || prev.error,
747
+ // تحديث صريح
748
+ data: result.data,
749
+ // تحديث صريح للبيانات
750
+ meta: result.meta,
751
+ // تحديث صريح
752
+ links: result.links,
753
+ // تحديث صريح
754
+ message: result.message,
755
+ validationErrors: result.validationErrors || [],
756
+ rawResponse: result.rawResponse
757
+ // isStale تم تعيينه إلى false في بداية execute، وسيظل كذلك
758
+ }));
759
+ }
713
760
  if (result.success) {
714
761
  savedCallbacks.current.onSuccess?.(actionName, result.message || "Action successful", result.data);
715
762
  options2.onSuccess?.(result.data, mutationContext);
716
763
  actionConfig.invalidates?.forEach((keyToInvalidate) => {
717
764
  const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
765
+ console.log(`[Invalidating] by prefix: ${prefix}`);
718
766
  globalStateManager.invalidateByPrefix(prefix);
719
767
  });
720
768
  } else {
@@ -723,12 +771,13 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
723
771
  }
724
772
  return result;
725
773
  } 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 }));
774
+ const apiError = error.response?.data || { status: 500, message: error.message };
775
+ if (shouldCache) {
776
+ globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
777
+ }
729
778
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
730
779
  options2.onError?.(apiError, mutationContext);
731
- return errorResult;
780
+ throw error;
732
781
  } finally {
733
782
  if (options2.onSettled) {
734
783
  options2.onSettled();
@@ -736,17 +785,11 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
736
785
  }
737
786
  };
738
787
  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
- }));
788
+ if (shouldCache) {
789
+ const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
790
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
791
+ globalStateManager.setState(cacheKey, () => createInitialState2());
792
+ }
750
793
  };
751
794
  acc[actionName] = { execute, reset };
752
795
  return acc;
@@ -778,31 +821,24 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
778
821
  for (const actionName in moduleConfig.actions) {
779
822
  if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
780
823
  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) {
824
+ if (actionConfig.cacheResponse !== false) {
800
825
  const query = queries[actionName]?.options;
801
826
  const input = actionConfig.hasQuery ? query : void 0;
802
- actions[actionName].execute(input);
827
+ const pathParams = JSON.parse(pathParamsString);
828
+ const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams });
829
+ states[actionName] = useApiActionState(
830
+ actionConfig,
831
+ cacheKey,
832
+ // [تصحيح] مرر `execute` مباشرة
833
+ actions[actionName].execute,
834
+ input,
835
+ enabled
836
+ );
837
+ } else {
838
+ states[actionName] = createInitialState2();
803
839
  }
804
840
  }
805
- }, [enabled, moduleConfig, actions, states, queries]);
841
+ }
806
842
  const lastBlurTimestamp = useRef4(Date.now());
807
843
  useEffect4(() => {
808
844
  if (!enabled || !refetchOnWindowFocus) return;
package/dist/index.cjs CHANGED
@@ -548,7 +548,6 @@ var GlobalStateManager = class {
548
548
  if (!this.store.has(key)) {
549
549
  const initialState = createInitialState();
550
550
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
551
- return initialState;
552
551
  }
553
552
  return this.store.get(key).state;
554
553
  }
@@ -570,14 +569,14 @@ var GlobalStateManager = class {
570
569
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
571
570
  */
572
571
  setState(key, updater) {
573
- const currentState = this.getSnapshot(key);
572
+ const item = this.store.get(key);
573
+ const currentState = item.state;
574
574
  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;
575
+ if (Object.is(currentState, newState)) {
576
+ return;
579
577
  }
580
- this.store.get(key).listeners.forEach((listener) => listener());
578
+ item.state = newState;
579
+ item.listeners.forEach((listener) => listener());
581
580
  }
582
581
  /**
583
582
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (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
@@ -506,7 +506,6 @@ var GlobalStateManager = class {
506
506
  if (!this.store.has(key)) {
507
507
  const initialState = createInitialState();
508
508
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
509
- return initialState;
510
509
  }
511
510
  return this.store.get(key).state;
512
511
  }
@@ -528,14 +527,14 @@ var GlobalStateManager = class {
528
527
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
529
528
  */
530
529
  setState(key, updater) {
531
- const currentState = this.getSnapshot(key);
530
+ const item = this.store.get(key);
531
+ const currentState = item.state;
532
532
  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;
533
+ if (Object.is(currentState, newState)) {
534
+ return;
537
535
  }
538
- this.store.get(key).listeners.forEach((listener) => listener());
536
+ item.state = newState;
537
+ item.listeners.forEach((listener) => listener());
539
538
  }
540
539
  /**
541
540
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
package/dist/server.cjs CHANGED
@@ -199,7 +199,6 @@ var GlobalStateManager = class {
199
199
  if (!this.store.has(key)) {
200
200
  const initialState = createInitialState();
201
201
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
202
- return initialState;
203
202
  }
204
203
  return this.store.get(key).state;
205
204
  }
@@ -221,14 +220,14 @@ var GlobalStateManager = class {
221
220
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
222
221
  */
223
222
  setState(key, updater) {
224
- const currentState = this.getSnapshot(key);
223
+ const item = this.store.get(key);
224
+ const currentState = item.state;
225
225
  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;
226
+ if (Object.is(currentState, newState)) {
227
+ return;
230
228
  }
231
- this.store.get(key).listeners.forEach((listener) => listener());
229
+ item.state = newState;
230
+ item.listeners.forEach((listener) => listener());
232
231
  }
233
232
  /**
234
233
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (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
@@ -165,7 +165,6 @@ var GlobalStateManager = class {
165
165
  if (!this.store.has(key)) {
166
166
  const initialState = createInitialState();
167
167
  this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
168
- return initialState;
169
168
  }
170
169
  return this.store.get(key).state;
171
170
  }
@@ -187,14 +186,14 @@ var GlobalStateManager = class {
187
186
  * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
188
187
  */
189
188
  setState(key, updater) {
190
- const currentState = this.getSnapshot(key);
189
+ const item = this.store.get(key);
190
+ const currentState = item.state;
191
191
  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;
192
+ if (Object.is(currentState, newState)) {
193
+ return;
196
194
  }
197
- this.store.get(key).listeners.forEach((listener) => listener());
195
+ item.state = newState;
196
+ item.listeners.forEach((listener) => listener());
198
197
  }
199
198
  /**
200
199
  * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (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.17",
4
4
  "description": "A flexible and powerful API client library for modern web applications.",
5
5
  "type": "module",
6
6