api-core-lib 12.0.13 → 12.0.14

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.
@@ -228,6 +228,7 @@ interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
228
228
  onMutate?: (variables: TInput) => TContext | Promise<TContext>;
229
229
  onSuccess?: (data: TOutput, context?: TContext) => void;
230
230
  onError?: (error: ApiError, context?: TContext) => void;
231
+ onSettled?: (data?: TOutput, error?: ApiError, context?: TContext) => void;
231
232
  }
232
233
  /** @description A fully-typed object representing the callable actions for a module. */
233
234
  type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>> = {
@@ -254,4 +255,4 @@ interface UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<
254
255
  dehydrate: () => string;
255
256
  }
256
257
 
257
- 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 };
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, UseApiQuery as f, ApiError as g, TokenManager as h, Middleware as i, RefreshTokenConfig as j, ActionConfig as k, ActionStateModule as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q };
@@ -228,6 +228,7 @@ interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
228
228
  onMutate?: (variables: TInput) => TContext | Promise<TContext>;
229
229
  onSuccess?: (data: TOutput, context?: TContext) => void;
230
230
  onError?: (error: ApiError, context?: TContext) => void;
231
+ onSettled?: (data?: TOutput, error?: ApiError, context?: TContext) => void;
231
232
  }
232
233
  /** @description A fully-typed object representing the callable actions for a module. */
233
234
  type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>> = {
@@ -254,4 +255,4 @@ interface UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<
254
255
  dehydrate: () => string;
255
256
  }
256
257
 
257
- 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 };
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, UseApiQuery as f, ApiError as g, TokenManager as h, Middleware as i, RefreshTokenConfig as j, ActionConfig as k, ActionStateModule as l, UseApiState as m, ActionState as n, ExecuteOptions as o, ModuleActions as p, ModuleStates as q };
@@ -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-CpwGDEpG.cjs';
2
+ import { R as RequestConfig, g as ApiError, S as StandardResponse, e as ActionOptions, l as ActionStateModule } from './apiModule.types-Cvp9QdAc.js';
3
3
 
4
4
  /**
5
5
  * Represents the internal state of the `useApiRecord` hook.
@@ -87,4 +87,54 @@ interface UseApiRecordReturn<T> {
87
87
  setState: Dispatch<SetStateAction<UseApiRecordState<T>>>;
88
88
  }
89
89
 
90
- export type { UseApiRecordConfig as U, UseApiRecordReturn as a, UseApiRecordState as b, UseApiRecordActions as c };
90
+ declare class GlobalStateManager {
91
+ private store;
92
+ getSnapshot<T>(key: string): ActionStateModule<T>;
93
+ /**
94
+ * يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
95
+ * @returns دالة لإلغاء الاشتراك.
96
+ */
97
+ subscribe(key: string, callback: () => void): () => void;
98
+ /**
99
+ * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
100
+ */
101
+ setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
102
+ /**
103
+ * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
104
+ */
105
+ invalidate(key: string): void;
106
+ /**
107
+ * [نسخة محدثة وأكثر قوة]
108
+ * يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
109
+ * @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
110
+ */
111
+ invalidateByPrefix(prefix: string): void;
112
+ /**
113
+ * Serializes the current state of the query store into a JSON string.
114
+ * This is used on the server to pass the initial state to the client.
115
+ * @returns A JSON string representing the dehydrated state.
116
+ */
117
+ dehydrate(): string;
118
+ /**
119
+ * Merges a dehydrated state object into the current store.
120
+ * This is used on the client to hydrate the state received from the server.
121
+ * @param hydratedState - A JSON string from the `dehydrate` method.
122
+ */
123
+ rehydrate(hydratedState: string): void;
124
+ }
125
+ declare const globalStateManager: GlobalStateManager;
126
+
127
+ /**
128
+ * يقوم بإنشاء مفتاح تخزين مؤقت فريد وثابت لإجراء معين ومدخلاته.
129
+ * هذا يضمن أن نفس الطلب ينتج دائمًا نفس المفتاح.
130
+ * @param moduleName - عادةً ما يكون `baseEndpoint` للموديول.
131
+ * @param actionName - اسم الإجراء (مثل 'list', 'create').
132
+ * @param input - بيانات الطلب (body/query params).
133
+ * @param callOptions - خيارات إضافية مثل `pathParams`.
134
+ * @returns سلسلة نصية فريدة تمثل مفتاح التخزين المؤقت.
135
+ */
136
+ declare const generateCacheKey: (moduleName: string, actionName: string, input?: unknown, callOptions?: {
137
+ pathParams?: Record<string, any>;
138
+ }) => string;
139
+
140
+ export { type UseApiRecordConfig as U, type UseApiRecordReturn as a, generateCacheKey as b, type UseApiRecordState as c, type UseApiRecordActions as d, globalStateManager as g };
@@ -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-CpwGDEpG.js';
2
+ import { R as RequestConfig, g as ApiError, S as StandardResponse, e as ActionOptions, l as ActionStateModule } from './apiModule.types-Cvp9QdAc.cjs';
3
3
 
4
4
  /**
5
5
  * Represents the internal state of the `useApiRecord` hook.
@@ -87,4 +87,54 @@ interface UseApiRecordReturn<T> {
87
87
  setState: Dispatch<SetStateAction<UseApiRecordState<T>>>;
88
88
  }
89
89
 
90
- export type { UseApiRecordConfig as U, UseApiRecordReturn as a, UseApiRecordState as b, UseApiRecordActions as c };
90
+ declare class GlobalStateManager {
91
+ private store;
92
+ getSnapshot<T>(key: string): ActionStateModule<T>;
93
+ /**
94
+ * يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
95
+ * @returns دالة لإلغاء الاشتراك.
96
+ */
97
+ subscribe(key: string, callback: () => void): () => void;
98
+ /**
99
+ * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
100
+ */
101
+ setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
102
+ /**
103
+ * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
104
+ */
105
+ invalidate(key: string): void;
106
+ /**
107
+ * [نسخة محدثة وأكثر قوة]
108
+ * يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
109
+ * @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
110
+ */
111
+ invalidateByPrefix(prefix: string): void;
112
+ /**
113
+ * Serializes the current state of the query store into a JSON string.
114
+ * This is used on the server to pass the initial state to the client.
115
+ * @returns A JSON string representing the dehydrated state.
116
+ */
117
+ dehydrate(): string;
118
+ /**
119
+ * Merges a dehydrated state object into the current store.
120
+ * This is used on the client to hydrate the state received from the server.
121
+ * @param hydratedState - A JSON string from the `dehydrate` method.
122
+ */
123
+ rehydrate(hydratedState: string): void;
124
+ }
125
+ declare const globalStateManager: GlobalStateManager;
126
+
127
+ /**
128
+ * يقوم بإنشاء مفتاح تخزين مؤقت فريد وثابت لإجراء معين ومدخلاته.
129
+ * هذا يضمن أن نفس الطلب ينتج دائمًا نفس المفتاح.
130
+ * @param moduleName - عادةً ما يكون `baseEndpoint` للموديول.
131
+ * @param actionName - اسم الإجراء (مثل 'list', 'create').
132
+ * @param input - بيانات الطلب (body/query params).
133
+ * @param callOptions - خيارات إضافية مثل `pathParams`.
134
+ * @returns سلسلة نصية فريدة تمثل مفتاح التخزين المؤقت.
135
+ */
136
+ declare const generateCacheKey: (moduleName: string, actionName: string, input?: unknown, callOptions?: {
137
+ pathParams?: Record<string, any>;
138
+ }) => string;
139
+
140
+ export { type UseApiRecordConfig as U, type UseApiRecordReturn as a, generateCacheKey as b, type UseApiRecordState as c, type UseApiRecordActions as d, globalStateManager as g };
package/dist/client.cjs CHANGED
@@ -34,6 +34,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
34
34
  var client_exports = {};
35
35
  __export(client_exports, {
36
36
  ApiModuleProvider: () => ApiModuleProvider,
37
+ generateCacheKey: () => generateCacheKey,
38
+ globalStateManager: () => globalStateManager,
37
39
  useApi: () => useApi,
38
40
  useApiModule: () => useApiModule,
39
41
  useApiRecord: () => useApiRecord,
@@ -697,7 +699,7 @@ function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
697
699
  } else if (enabled && state.isStale && !state.loading) {
698
700
  actionExecutor(input);
699
701
  }
700
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, input]);
702
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
701
703
  return state;
702
704
  }
703
705
  function useModuleContext() {
@@ -707,14 +709,6 @@ function useModuleContext() {
707
709
  }
708
710
  return context;
709
711
  }
710
- var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
711
- const params = { path: callOptions.pathParams, body: input };
712
- try {
713
- return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
714
- } catch (error) {
715
- return `${moduleName}/${actionName}::${Date.now()}`;
716
- }
717
- };
718
712
  function useApiModule(axiosInstance, moduleConfig, options = {}) {
719
713
  const { refetchOnWindowFocus = true, onSuccess, onError, pathParams: modulePathParams, enabled = true, hydratedState } = options;
720
714
  const pathParamsString = (0, import_react4.useMemo)(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
@@ -765,6 +759,10 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
765
759
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
766
760
  options2.onError?.(apiError, mutationContext);
767
761
  return errorResult;
762
+ } finally {
763
+ if (options2.onSettled) {
764
+ options2.onSettled();
765
+ }
768
766
  }
769
767
  };
770
768
  const reset = (input, options2 = {}) => {
@@ -865,9 +863,83 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
865
863
  }, []);
866
864
  return { actions, states, queries, dehydrate };
867
865
  }
866
+
867
+ // src/core/client.ts
868
+ var import_axios3 = __toESM(require("axios"), 1);
869
+ var import_uuid = require("uuid");
870
+
871
+ // src/core/cache.ts
872
+ var CacheManager = class {
873
+ constructor() {
874
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
875
+ __publicField(this, "defaultDuration", 15 * 60 * 1e3);
876
+ }
877
+ // 15 minutes
878
+ set(key, data, duration) {
879
+ this.cache.set(key, {
880
+ data,
881
+ timestamp: Date.now(),
882
+ duration: duration || this.defaultDuration
883
+ });
884
+ }
885
+ get(key) {
886
+ const item = this.cache.get(key);
887
+ if (!item) return null;
888
+ const isExpired = Date.now() - item.timestamp > item.duration;
889
+ if (isExpired) {
890
+ this.cache.delete(key);
891
+ return null;
892
+ }
893
+ return item.data;
894
+ }
895
+ /**
896
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
897
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
898
+ */
899
+ getWithMeta(key) {
900
+ const item = this.cache.get(key);
901
+ if (!item) return null;
902
+ const isExpired = Date.now() - item.timestamp > item.duration;
903
+ if (isExpired) {
904
+ this.cache.delete(key);
905
+ return null;
906
+ }
907
+ return item;
908
+ }
909
+ delete(key) {
910
+ this.cache.delete(key);
911
+ }
912
+ clear() {
913
+ this.cache.clear();
914
+ }
915
+ invalidateByPrefix(prefix) {
916
+ const keysToDelete = [];
917
+ for (const key of this.cache.keys()) {
918
+ if (key.startsWith(prefix)) {
919
+ keysToDelete.push(key);
920
+ }
921
+ }
922
+ keysToDelete.forEach((key) => this.cache.delete(key));
923
+ console.log(`Invalidated ${keysToDelete.length} cache entries with prefix: ${prefix}`);
924
+ }
925
+ };
926
+ var cacheManager = new CacheManager();
927
+
928
+ // src/core/cacheKey.ts
929
+ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
930
+ const params = { path: callOptions.pathParams, body: input };
931
+ try {
932
+ return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
933
+ } catch (error) {
934
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
935
+ return `${moduleName}/${actionName}::${Date.now()}`;
936
+ }
937
+ };
868
938
  // Annotate the CommonJS export names for ESM import in node:
869
939
  0 && (module.exports = {
870
940
  ApiModuleProvider,
941
+ generateCacheKey,
942
+ globalStateManager,
871
943
  useApi,
872
944
  useApiModule,
873
945
  useApiRecord,
package/dist/client.d.cts CHANGED
@@ -1,6 +1,7 @@
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-CpwGDEpG.cjs';
3
- import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-B45E0qux.cjs';
2
+ import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-Cvp9QdAc.cjs';
3
+ import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './cacheKey-BNQ1ii6y.cjs';
4
+ export { b as generateCacheKey, g as globalStateManager } from './cacheKey-BNQ1ii6y.cjs';
4
5
  import * as React from 'react';
5
6
 
6
7
  declare function useApi<T>(axiosInstance: AxiosInstance, config: UseApiConfig<T>): any;
package/dist/client.d.ts CHANGED
@@ -1,6 +1,7 @@
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-CpwGDEpG.js';
3
- import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-DlrlXL1t.js';
2
+ import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn } from './apiModule.types-Cvp9QdAc.js';
3
+ import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './cacheKey-BJQaehcQ.js';
4
+ export { b as generateCacheKey, g as globalStateManager } from './cacheKey-BJQaehcQ.js';
4
5
  import * as React from 'react';
5
6
 
6
7
  declare function useApi<T>(axiosInstance: AxiosInstance, config: UseApiConfig<T>): any;
package/dist/client.js CHANGED
@@ -658,7 +658,7 @@ function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
658
658
  } else if (enabled && state.isStale && !state.loading) {
659
659
  actionExecutor(input);
660
660
  }
661
- }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, input]);
661
+ }, [enabled, state.isStale, state.loading, state.called, actionConfig.autoFetch, actionExecutor, JSON.stringify(input)]);
662
662
  return state;
663
663
  }
664
664
  function useModuleContext() {
@@ -668,14 +668,6 @@ function useModuleContext() {
668
668
  }
669
669
  return context;
670
670
  }
671
- var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
672
- const params = { path: callOptions.pathParams, body: input };
673
- try {
674
- return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
675
- } catch (error) {
676
- return `${moduleName}/${actionName}::${Date.now()}`;
677
- }
678
- };
679
671
  function useApiModule(axiosInstance, moduleConfig, options = {}) {
680
672
  const { refetchOnWindowFocus = true, onSuccess, onError, pathParams: modulePathParams, enabled = true, hydratedState } = options;
681
673
  const pathParamsString = useMemo3(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
@@ -726,6 +718,10 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
726
718
  savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
727
719
  options2.onError?.(apiError, mutationContext);
728
720
  return errorResult;
721
+ } finally {
722
+ if (options2.onSettled) {
723
+ options2.onSettled();
724
+ }
729
725
  }
730
726
  };
731
727
  const reset = (input, options2 = {}) => {
@@ -826,8 +822,82 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
826
822
  }, []);
827
823
  return { actions, states, queries, dehydrate };
828
824
  }
825
+
826
+ // src/core/client.ts
827
+ import axios3 from "axios";
828
+ import { v4 as uuidv4 } from "uuid";
829
+
830
+ // src/core/cache.ts
831
+ var CacheManager = class {
832
+ constructor() {
833
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
834
+ __publicField(this, "defaultDuration", 15 * 60 * 1e3);
835
+ }
836
+ // 15 minutes
837
+ set(key, data, duration) {
838
+ this.cache.set(key, {
839
+ data,
840
+ timestamp: Date.now(),
841
+ duration: duration || this.defaultDuration
842
+ });
843
+ }
844
+ get(key) {
845
+ const item = this.cache.get(key);
846
+ if (!item) return null;
847
+ const isExpired = Date.now() - item.timestamp > item.duration;
848
+ if (isExpired) {
849
+ this.cache.delete(key);
850
+ return null;
851
+ }
852
+ return item.data;
853
+ }
854
+ /**
855
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
856
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
857
+ */
858
+ getWithMeta(key) {
859
+ const item = this.cache.get(key);
860
+ if (!item) return null;
861
+ const isExpired = Date.now() - item.timestamp > item.duration;
862
+ if (isExpired) {
863
+ this.cache.delete(key);
864
+ return null;
865
+ }
866
+ return item;
867
+ }
868
+ delete(key) {
869
+ this.cache.delete(key);
870
+ }
871
+ clear() {
872
+ this.cache.clear();
873
+ }
874
+ invalidateByPrefix(prefix) {
875
+ const keysToDelete = [];
876
+ for (const key of this.cache.keys()) {
877
+ if (key.startsWith(prefix)) {
878
+ keysToDelete.push(key);
879
+ }
880
+ }
881
+ keysToDelete.forEach((key) => this.cache.delete(key));
882
+ console.log(`Invalidated ${keysToDelete.length} cache entries with prefix: ${prefix}`);
883
+ }
884
+ };
885
+ var cacheManager = new CacheManager();
886
+
887
+ // src/core/cacheKey.ts
888
+ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
889
+ const params = { path: callOptions.pathParams, body: input };
890
+ try {
891
+ return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
892
+ } catch (error) {
893
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
894
+ return `${moduleName}/${actionName}::${Date.now()}`;
895
+ }
896
+ };
829
897
  export {
830
898
  ApiModuleProvider,
899
+ generateCacheKey,
900
+ globalStateManager,
831
901
  useApi,
832
902
  useApiModule,
833
903
  useApiRecord,
package/dist/index.cjs CHANGED
@@ -38,6 +38,7 @@ __export(index_exports, {
38
38
  createApiActions: () => createApiActions,
39
39
  createApiClient: () => createApiClient,
40
40
  createApiServices: () => createApiServices,
41
+ generateCacheKey: () => generateCacheKey,
41
42
  globalStateManager: () => globalStateManager,
42
43
  processResponse: () => processResponse
43
44
  });
@@ -690,6 +691,17 @@ var CacheManager = class {
690
691
  }
691
692
  };
692
693
  var cacheManager = new CacheManager();
694
+
695
+ // src/core/cacheKey.ts
696
+ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
697
+ const params = { path: callOptions.pathParams, body: input };
698
+ try {
699
+ return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
700
+ } catch (error) {
701
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
702
+ return `${moduleName}/${actionName}::${Date.now()}`;
703
+ }
704
+ };
693
705
  // Annotate the CommonJS export names for ESM import in node:
694
706
  0 && (module.exports = {
695
707
  buildPaginateQuery,
@@ -698,6 +710,7 @@ var cacheManager = new CacheManager();
698
710
  createApiActions,
699
711
  createApiClient,
700
712
  createApiServices,
713
+ generateCacheKey,
701
714
  globalStateManager,
702
715
  processResponse
703
716
  });
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-CpwGDEpG.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-CpwGDEpG.cjs';
4
- export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-B45E0qux.cjs';
2
+ import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, Q as QueryOptions, f as UseApiQuery, g as ApiError, L as LogLevel } from './apiModule.types-Cvp9QdAc.cjs';
3
+ export { k as ActionConfig, n as ActionState, l as ActionStateModule, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, i as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, j as RefreshTokenConfig, h as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError } from './apiModule.types-Cvp9QdAc.cjs';
4
+ export { d as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, c as UseApiRecordState, b as generateCacheKey, g as globalStateManager } from './cacheKey-BNQ1ii6y.cjs';
5
5
  import 'react';
6
6
 
7
7
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
@@ -72,43 +72,6 @@ declare function createApiActions<TActions extends Record<string, {
72
72
  [K in keyof TActions]: ApiAction<TActions[K]['requestType'], TActions[K]['responseType']>;
73
73
  };
74
74
 
75
- declare class GlobalStateManager {
76
- private store;
77
- getSnapshot<T>(key: string): ActionStateModule<T>;
78
- /**
79
- * يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
80
- * @returns دالة لإلغاء الاشتراك.
81
- */
82
- subscribe(key: string, callback: () => void): () => void;
83
- /**
84
- * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
85
- */
86
- setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
87
- /**
88
- * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
89
- */
90
- invalidate(key: string): void;
91
- /**
92
- * [نسخة محدثة وأكثر قوة]
93
- * يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
94
- * @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
95
- */
96
- invalidateByPrefix(prefix: string): void;
97
- /**
98
- * Serializes the current state of the query store into a JSON string.
99
- * This is used on the server to pass the initial state to the client.
100
- * @returns A JSON string representing the dehydrated state.
101
- */
102
- dehydrate(): string;
103
- /**
104
- * Merges a dehydrated state object into the current store.
105
- * This is used on the client to hydrate the state received from the server.
106
- * @param hydratedState - A JSON string from the `dehydrate` method.
107
- */
108
- rehydrate(hydratedState: string): void;
109
- }
110
- declare const globalStateManager: GlobalStateManager;
111
-
112
75
  /**
113
76
  * [نسخة مطورة] يبني سلسلة استعلام (query string) من كائن الخيارات.
114
77
  * يدعم الآن الفلاتر المتداخلة (filter[key]=value) والترتيب المتعدد.
@@ -225,4 +188,4 @@ interface UseApiResourceReturn<T, TCreate, TUpdate, TPathParams> {
225
188
  setQuery: React.Dispatch<React.SetStateAction<QueryOptions>>;
226
189
  }
227
190
 
228
- export { ActionConfigModule, ActionOptions, ActionStateModule, ApiClientConfig, ApiError, type ApiResourceStatus, LogLevel, QueryOptions, RequestConfig, StandardResponse, type UseApiActions, UseApiQuery, type UseApiResourceActions, type UseApiResourceConfig, type UseApiResourceReturn, type UseApiResourceState, type UseApiReturn, buildPaginateQuery, cacheManager, callDynamicApi, createApiActions, createApiClient, createApiServices, globalStateManager, processResponse };
191
+ export { ActionConfigModule, ActionOptions, ApiClientConfig, ApiError, type ApiResourceStatus, LogLevel, QueryOptions, RequestConfig, StandardResponse, type UseApiActions, UseApiQuery, type UseApiResourceActions, type UseApiResourceConfig, type UseApiResourceReturn, type UseApiResourceState, type UseApiReturn, buildPaginateQuery, cacheManager, callDynamicApi, createApiActions, createApiClient, createApiServices, processResponse };
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-CpwGDEpG.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-CpwGDEpG.js';
4
- export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-DlrlXL1t.js';
2
+ import { d as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, e as ActionOptions, R as RequestConfig, Q as QueryOptions, f as UseApiQuery, g as ApiError, L as LogLevel } from './apiModule.types-Cvp9QdAc.js';
3
+ export { k as ActionConfig, n as ActionState, l as ActionStateModule, a as ApiModuleConfig, E as ExecutableAction, o as ExecuteOptions, I as InputOf, i as Middleware, M as MiddlewareContext, p as ModuleActions, q as ModuleStates, O as OutputOf, P as PaginationMeta, j as RefreshTokenConfig, h as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, m as UseApiState, V as ValidationError } from './apiModule.types-Cvp9QdAc.js';
4
+ export { d as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, c as UseApiRecordState, b as generateCacheKey, g as globalStateManager } from './cacheKey-BJQaehcQ.js';
5
5
  import 'react';
6
6
 
7
7
  declare function createApiClient(config: ApiClientConfig): AxiosInstance;
@@ -72,43 +72,6 @@ declare function createApiActions<TActions extends Record<string, {
72
72
  [K in keyof TActions]: ApiAction<TActions[K]['requestType'], TActions[K]['responseType']>;
73
73
  };
74
74
 
75
- declare class GlobalStateManager {
76
- private store;
77
- getSnapshot<T>(key: string): ActionStateModule<T>;
78
- /**
79
- * يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
80
- * @returns دالة لإلغاء الاشتراك.
81
- */
82
- subscribe(key: string, callback: () => void): () => void;
83
- /**
84
- * يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
85
- */
86
- setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
87
- /**
88
- * يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
89
- */
90
- invalidate(key: string): void;
91
- /**
92
- * [نسخة محدثة وأكثر قوة]
93
- * يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
94
- * @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
95
- */
96
- invalidateByPrefix(prefix: string): void;
97
- /**
98
- * Serializes the current state of the query store into a JSON string.
99
- * This is used on the server to pass the initial state to the client.
100
- * @returns A JSON string representing the dehydrated state.
101
- */
102
- dehydrate(): string;
103
- /**
104
- * Merges a dehydrated state object into the current store.
105
- * This is used on the client to hydrate the state received from the server.
106
- * @param hydratedState - A JSON string from the `dehydrate` method.
107
- */
108
- rehydrate(hydratedState: string): void;
109
- }
110
- declare const globalStateManager: GlobalStateManager;
111
-
112
75
  /**
113
76
  * [نسخة مطورة] يبني سلسلة استعلام (query string) من كائن الخيارات.
114
77
  * يدعم الآن الفلاتر المتداخلة (filter[key]=value) والترتيب المتعدد.
@@ -225,4 +188,4 @@ interface UseApiResourceReturn<T, TCreate, TUpdate, TPathParams> {
225
188
  setQuery: React.Dispatch<React.SetStateAction<QueryOptions>>;
226
189
  }
227
190
 
228
- export { ActionConfigModule, ActionOptions, ActionStateModule, ApiClientConfig, ApiError, type ApiResourceStatus, LogLevel, QueryOptions, RequestConfig, StandardResponse, type UseApiActions, UseApiQuery, type UseApiResourceActions, type UseApiResourceConfig, type UseApiResourceReturn, type UseApiResourceState, type UseApiReturn, buildPaginateQuery, cacheManager, callDynamicApi, createApiActions, createApiClient, createApiServices, globalStateManager, processResponse };
191
+ export { ActionConfigModule, ActionOptions, ApiClientConfig, ApiError, type ApiResourceStatus, LogLevel, QueryOptions, RequestConfig, StandardResponse, type UseApiActions, UseApiQuery, type UseApiResourceActions, type UseApiResourceConfig, type UseApiResourceReturn, type UseApiResourceState, type UseApiReturn, buildPaginateQuery, cacheManager, callDynamicApi, createApiActions, createApiClient, createApiServices, processResponse };
package/dist/index.js CHANGED
@@ -649,6 +649,17 @@ var CacheManager = class {
649
649
  }
650
650
  };
651
651
  var cacheManager = new CacheManager();
652
+
653
+ // src/core/cacheKey.ts
654
+ var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
655
+ const params = { path: callOptions.pathParams, body: input };
656
+ try {
657
+ return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
658
+ } catch (error) {
659
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
660
+ return `${moduleName}/${actionName}::${Date.now()}`;
661
+ }
662
+ };
652
663
  export {
653
664
  buildPaginateQuery,
654
665
  cacheManager,
@@ -656,6 +667,7 @@ export {
656
667
  createApiActions,
657
668
  createApiClient,
658
669
  createApiServices,
670
+ generateCacheKey,
659
671
  globalStateManager,
660
672
  processResponse
661
673
  };
package/dist/server.cjs CHANGED
@@ -286,15 +286,94 @@ var GlobalStateManager = class {
286
286
  };
287
287
  var globalStateManager = new GlobalStateManager();
288
288
 
289
- // src/server.ts
289
+ // src/hooks/useApi.ts
290
+ var import_react = require("react");
291
+
292
+ // src/hooks/useApiRecord/index.ts
293
+ var import_react2 = require("react");
294
+
295
+ // src/hooks/useDeepCompareEffect/index.ts
296
+ var import_react3 = require("react");
297
+ var import_fast_deep_equal = __toESM(require("fast-deep-equal"), 1);
298
+
299
+ // src/hooks/useApiModule/useApiModule.ts
300
+ var import_react4 = require("react");
301
+ var ApiModuleContext = (0, import_react4.createContext)(null);
302
+ var ApiModuleProvider = ApiModuleContext.Provider;
303
+
304
+ // src/core/client.ts
305
+ var import_axios3 = __toESM(require("axios"), 1);
306
+ var import_uuid = require("uuid");
307
+
308
+ // src/core/cache.ts
309
+ var CacheManager = class {
310
+ constructor() {
311
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
312
+ __publicField(this, "defaultDuration", 15 * 60 * 1e3);
313
+ }
314
+ // 15 minutes
315
+ set(key, data, duration) {
316
+ this.cache.set(key, {
317
+ data,
318
+ timestamp: Date.now(),
319
+ duration: duration || this.defaultDuration
320
+ });
321
+ }
322
+ get(key) {
323
+ const item = this.cache.get(key);
324
+ if (!item) return null;
325
+ const isExpired = Date.now() - item.timestamp > item.duration;
326
+ if (isExpired) {
327
+ this.cache.delete(key);
328
+ return null;
329
+ }
330
+ return item.data;
331
+ }
332
+ /**
333
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
334
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
335
+ */
336
+ getWithMeta(key) {
337
+ const item = this.cache.get(key);
338
+ if (!item) return null;
339
+ const isExpired = Date.now() - item.timestamp > item.duration;
340
+ if (isExpired) {
341
+ this.cache.delete(key);
342
+ return null;
343
+ }
344
+ return item;
345
+ }
346
+ delete(key) {
347
+ this.cache.delete(key);
348
+ }
349
+ clear() {
350
+ this.cache.clear();
351
+ }
352
+ invalidateByPrefix(prefix) {
353
+ const keysToDelete = [];
354
+ for (const key of this.cache.keys()) {
355
+ if (key.startsWith(prefix)) {
356
+ keysToDelete.push(key);
357
+ }
358
+ }
359
+ keysToDelete.forEach((key) => this.cache.delete(key));
360
+ console.log(`Invalidated ${keysToDelete.length} cache entries with prefix: ${prefix}`);
361
+ }
362
+ };
363
+ var cacheManager = new CacheManager();
364
+
365
+ // src/core/cacheKey.ts
290
366
  var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
291
367
  const params = { path: callOptions.pathParams, body: input };
292
368
  try {
293
369
  return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
294
370
  } catch (error) {
371
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
295
372
  return `${moduleName}/${actionName}::${Date.now()}`;
296
373
  }
297
374
  };
375
+
376
+ // src/server.ts
298
377
  function createServerApi(apiClient, moduleConfig) {
299
378
  return {
300
379
  /**
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-CpwGDEpG.cjs';
2
+ import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-Cvp9QdAc.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-CpwGDEpG.js';
2
+ import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-Cvp9QdAc.js';
3
3
  import 'react';
4
4
 
5
5
  /**
package/dist/server.js CHANGED
@@ -252,15 +252,94 @@ var GlobalStateManager = class {
252
252
  };
253
253
  var globalStateManager = new GlobalStateManager();
254
254
 
255
- // src/server.ts
255
+ // src/hooks/useApi.ts
256
+ import { useState, useEffect, useCallback, useRef, useMemo } from "react";
257
+
258
+ // src/hooks/useApiRecord/index.ts
259
+ import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef2, useMemo as useMemo2 } from "react";
260
+
261
+ // src/hooks/useDeepCompareEffect/index.ts
262
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
263
+ import isEqual from "fast-deep-equal";
264
+
265
+ // src/hooks/useApiModule/useApiModule.ts
266
+ import { createContext, useContext, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState3, useSyncExternalStore } from "react";
267
+ var ApiModuleContext = createContext(null);
268
+ var ApiModuleProvider = ApiModuleContext.Provider;
269
+
270
+ // src/core/client.ts
271
+ import axios3 from "axios";
272
+ import { v4 as uuidv4 } from "uuid";
273
+
274
+ // src/core/cache.ts
275
+ var CacheManager = class {
276
+ constructor() {
277
+ __publicField(this, "cache", /* @__PURE__ */ new Map());
278
+ __publicField(this, "defaultDuration", 15 * 60 * 1e3);
279
+ }
280
+ // 15 minutes
281
+ set(key, data, duration) {
282
+ this.cache.set(key, {
283
+ data,
284
+ timestamp: Date.now(),
285
+ duration: duration || this.defaultDuration
286
+ });
287
+ }
288
+ get(key) {
289
+ const item = this.cache.get(key);
290
+ if (!item) return null;
291
+ const isExpired = Date.now() - item.timestamp > item.duration;
292
+ if (isExpired) {
293
+ this.cache.delete(key);
294
+ return null;
295
+ }
296
+ return item.data;
297
+ }
298
+ /**
299
+ * [FIX] تم تحويلها إلى دالة عامة (generic) لتعيد النوع الصحيح.
300
+ * الآن بدلًا من إرجاع CacheItem<unknown>، ستُرجع CacheItem<T>.
301
+ */
302
+ getWithMeta(key) {
303
+ const item = this.cache.get(key);
304
+ if (!item) return null;
305
+ const isExpired = Date.now() - item.timestamp > item.duration;
306
+ if (isExpired) {
307
+ this.cache.delete(key);
308
+ return null;
309
+ }
310
+ return item;
311
+ }
312
+ delete(key) {
313
+ this.cache.delete(key);
314
+ }
315
+ clear() {
316
+ this.cache.clear();
317
+ }
318
+ invalidateByPrefix(prefix) {
319
+ const keysToDelete = [];
320
+ for (const key of this.cache.keys()) {
321
+ if (key.startsWith(prefix)) {
322
+ keysToDelete.push(key);
323
+ }
324
+ }
325
+ keysToDelete.forEach((key) => this.cache.delete(key));
326
+ console.log(`Invalidated ${keysToDelete.length} cache entries with prefix: ${prefix}`);
327
+ }
328
+ };
329
+ var cacheManager = new CacheManager();
330
+
331
+ // src/core/cacheKey.ts
256
332
  var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
257
333
  const params = { path: callOptions.pathParams, body: input };
258
334
  try {
259
335
  return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
260
336
  } catch (error) {
337
+ console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
261
338
  return `${moduleName}/${actionName}::${Date.now()}`;
262
339
  }
263
340
  };
341
+
342
+ // src/server.ts
264
343
  function createServerApi(apiClient, moduleConfig) {
265
344
  return {
266
345
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "api-core-lib",
3
- "version": "12.0.13",
3
+ "version": "12.0.14",
4
4
  "description": "A flexible and powerful API client library for modern web applications.",
5
5
  "type": "module",
6
6