api-core-lib 12.0.12 → 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.
- package/dist/{apiModule.types-CpwGDEpG.d.cts → apiModule.types-Cvp9QdAc.d.cts} +2 -1
- package/dist/{apiModule.types-CpwGDEpG.d.ts → apiModule.types-Cvp9QdAc.d.ts} +2 -1
- package/dist/{useApiRecord.types-B45E0qux.d.cts → cacheKey-BJQaehcQ.d.ts} +52 -2
- package/dist/{useApiRecord.types-DlrlXL1t.d.ts → cacheKey-BNQ1ii6y.d.cts} +52 -2
- package/dist/client.cjs +93 -14
- package/dist/client.d.cts +3 -2
- package/dist/client.d.ts +3 -2
- package/dist/client.js +91 -14
- package/dist/index.cjs +19 -4
- package/dist/index.d.cts +4 -44
- package/dist/index.d.ts +4 -44
- package/dist/index.js +18 -4
- package/dist/server.cjs +86 -5
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +86 -5
- package/package.json +1 -1
|
@@ -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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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,
|
|
@@ -586,11 +588,13 @@ var GlobalStateManager = class {
|
|
|
586
588
|
constructor() {
|
|
587
589
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
588
590
|
}
|
|
589
|
-
/**
|
|
590
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
591
|
-
*/
|
|
592
591
|
getSnapshot(key) {
|
|
593
|
-
|
|
592
|
+
if (!this.store.has(key)) {
|
|
593
|
+
const initialState = createInitialState();
|
|
594
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
595
|
+
return initialState;
|
|
596
|
+
}
|
|
597
|
+
return this.store.get(key).state;
|
|
594
598
|
}
|
|
595
599
|
/**
|
|
596
600
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -679,9 +683,14 @@ var globalStateManager = new GlobalStateManager();
|
|
|
679
683
|
var ApiModuleContext = (0, import_react4.createContext)(null);
|
|
680
684
|
var ApiModuleProvider = ApiModuleContext.Provider;
|
|
681
685
|
function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
|
|
686
|
+
const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
|
|
687
|
+
const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
|
|
682
688
|
const state = (0, import_react4.useSyncExternalStore)(
|
|
683
689
|
(callback) => globalStateManager.subscribe(cacheKey, callback),
|
|
684
|
-
|
|
690
|
+
getClientSnapshot,
|
|
691
|
+
// لقطة العميل
|
|
692
|
+
getServerSnapshot
|
|
693
|
+
// لقطة الخادم
|
|
685
694
|
);
|
|
686
695
|
const input = actionConfig.hasQuery ? state.options : void 0;
|
|
687
696
|
(0, import_react4.useEffect)(() => {
|
|
@@ -690,7 +699,7 @@ function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
|
|
|
690
699
|
} else if (enabled && state.isStale && !state.loading) {
|
|
691
700
|
actionExecutor(input);
|
|
692
701
|
}
|
|
693
|
-
}, [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)]);
|
|
694
703
|
return state;
|
|
695
704
|
}
|
|
696
705
|
function useModuleContext() {
|
|
@@ -700,14 +709,6 @@ function useModuleContext() {
|
|
|
700
709
|
}
|
|
701
710
|
return context;
|
|
702
711
|
}
|
|
703
|
-
var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
|
|
704
|
-
const params = { path: callOptions.pathParams, body: input };
|
|
705
|
-
try {
|
|
706
|
-
return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
|
|
707
|
-
} catch (error) {
|
|
708
|
-
return `${moduleName}/${actionName}::${Date.now()}`;
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
712
|
function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
712
713
|
const { refetchOnWindowFocus = true, onSuccess, onError, pathParams: modulePathParams, enabled = true, hydratedState } = options;
|
|
713
714
|
const pathParamsString = (0, import_react4.useMemo)(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
@@ -758,6 +759,10 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
758
759
|
savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
|
|
759
760
|
options2.onError?.(apiError, mutationContext);
|
|
760
761
|
return errorResult;
|
|
762
|
+
} finally {
|
|
763
|
+
if (options2.onSettled) {
|
|
764
|
+
options2.onSettled();
|
|
765
|
+
}
|
|
761
766
|
}
|
|
762
767
|
};
|
|
763
768
|
const reset = (input, options2 = {}) => {
|
|
@@ -858,9 +863,83 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
858
863
|
}, []);
|
|
859
864
|
return { actions, states, queries, dehydrate };
|
|
860
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
|
+
};
|
|
861
938
|
// Annotate the CommonJS export names for ESM import in node:
|
|
862
939
|
0 && (module.exports = {
|
|
863
940
|
ApiModuleProvider,
|
|
941
|
+
generateCacheKey,
|
|
942
|
+
globalStateManager,
|
|
864
943
|
useApi,
|
|
865
944
|
useApiModule,
|
|
866
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-
|
|
3
|
-
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './
|
|
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-
|
|
3
|
-
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './
|
|
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
|
@@ -547,11 +547,13 @@ var GlobalStateManager = class {
|
|
|
547
547
|
constructor() {
|
|
548
548
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
549
549
|
}
|
|
550
|
-
/**
|
|
551
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
552
|
-
*/
|
|
553
550
|
getSnapshot(key) {
|
|
554
|
-
|
|
551
|
+
if (!this.store.has(key)) {
|
|
552
|
+
const initialState = createInitialState();
|
|
553
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
554
|
+
return initialState;
|
|
555
|
+
}
|
|
556
|
+
return this.store.get(key).state;
|
|
555
557
|
}
|
|
556
558
|
/**
|
|
557
559
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -640,9 +642,14 @@ var globalStateManager = new GlobalStateManager();
|
|
|
640
642
|
var ApiModuleContext = createContext(null);
|
|
641
643
|
var ApiModuleProvider = ApiModuleContext.Provider;
|
|
642
644
|
function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
|
|
645
|
+
const getClientSnapshot = () => globalStateManager.getSnapshot(cacheKey);
|
|
646
|
+
const getServerSnapshot = () => globalStateManager.getSnapshot(cacheKey);
|
|
643
647
|
const state = useSyncExternalStore(
|
|
644
648
|
(callback) => globalStateManager.subscribe(cacheKey, callback),
|
|
645
|
-
|
|
649
|
+
getClientSnapshot,
|
|
650
|
+
// لقطة العميل
|
|
651
|
+
getServerSnapshot
|
|
652
|
+
// لقطة الخادم
|
|
646
653
|
);
|
|
647
654
|
const input = actionConfig.hasQuery ? state.options : void 0;
|
|
648
655
|
useEffect4(() => {
|
|
@@ -651,7 +658,7 @@ function useApiActionState(actionConfig, cacheKey, actionExecutor, enabled) {
|
|
|
651
658
|
} else if (enabled && state.isStale && !state.loading) {
|
|
652
659
|
actionExecutor(input);
|
|
653
660
|
}
|
|
654
|
-
}, [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)]);
|
|
655
662
|
return state;
|
|
656
663
|
}
|
|
657
664
|
function useModuleContext() {
|
|
@@ -661,14 +668,6 @@ function useModuleContext() {
|
|
|
661
668
|
}
|
|
662
669
|
return context;
|
|
663
670
|
}
|
|
664
|
-
var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
|
|
665
|
-
const params = { path: callOptions.pathParams, body: input };
|
|
666
|
-
try {
|
|
667
|
-
return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
|
|
668
|
-
} catch (error) {
|
|
669
|
-
return `${moduleName}/${actionName}::${Date.now()}`;
|
|
670
|
-
}
|
|
671
|
-
};
|
|
672
671
|
function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
673
672
|
const { refetchOnWindowFocus = true, onSuccess, onError, pathParams: modulePathParams, enabled = true, hydratedState } = options;
|
|
674
673
|
const pathParamsString = useMemo3(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
@@ -719,6 +718,10 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
719
718
|
savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
|
|
720
719
|
options2.onError?.(apiError, mutationContext);
|
|
721
720
|
return errorResult;
|
|
721
|
+
} finally {
|
|
722
|
+
if (options2.onSettled) {
|
|
723
|
+
options2.onSettled();
|
|
724
|
+
}
|
|
722
725
|
}
|
|
723
726
|
};
|
|
724
727
|
const reset = (input, options2 = {}) => {
|
|
@@ -819,8 +822,82 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
819
822
|
}, []);
|
|
820
823
|
return { actions, states, queries, dehydrate };
|
|
821
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
|
+
};
|
|
822
897
|
export {
|
|
823
898
|
ApiModuleProvider,
|
|
899
|
+
generateCacheKey,
|
|
900
|
+
globalStateManager,
|
|
824
901
|
useApi,
|
|
825
902
|
useApiModule,
|
|
826
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
|
});
|
|
@@ -543,11 +544,13 @@ var GlobalStateManager = class {
|
|
|
543
544
|
constructor() {
|
|
544
545
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
545
546
|
}
|
|
546
|
-
/**
|
|
547
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
548
|
-
*/
|
|
549
547
|
getSnapshot(key) {
|
|
550
|
-
|
|
548
|
+
if (!this.store.has(key)) {
|
|
549
|
+
const initialState = createInitialState();
|
|
550
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
551
|
+
return initialState;
|
|
552
|
+
}
|
|
553
|
+
return this.store.get(key).state;
|
|
551
554
|
}
|
|
552
555
|
/**
|
|
553
556
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -688,6 +691,17 @@ var CacheManager = class {
|
|
|
688
691
|
}
|
|
689
692
|
};
|
|
690
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
|
+
};
|
|
691
705
|
// Annotate the CommonJS export names for ESM import in node:
|
|
692
706
|
0 && (module.exports = {
|
|
693
707
|
buildPaginateQuery,
|
|
@@ -696,6 +710,7 @@ var cacheManager = new CacheManager();
|
|
|
696
710
|
createApiActions,
|
|
697
711
|
createApiClient,
|
|
698
712
|
createApiServices,
|
|
713
|
+
generateCacheKey,
|
|
699
714
|
globalStateManager,
|
|
700
715
|
processResponse
|
|
701
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,
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
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,46 +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
|
-
/**
|
|
78
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
79
|
-
*/
|
|
80
|
-
getSnapshot<T>(key: string): ActionStateModule<T>;
|
|
81
|
-
/**
|
|
82
|
-
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
83
|
-
* @returns دالة لإلغاء الاشتراك.
|
|
84
|
-
*/
|
|
85
|
-
subscribe(key: string, callback: () => void): () => void;
|
|
86
|
-
/**
|
|
87
|
-
* يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
|
|
88
|
-
*/
|
|
89
|
-
setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
|
|
90
|
-
/**
|
|
91
|
-
* يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
|
|
92
|
-
*/
|
|
93
|
-
invalidate(key: string): void;
|
|
94
|
-
/**
|
|
95
|
-
* [نسخة محدثة وأكثر قوة]
|
|
96
|
-
* يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
|
|
97
|
-
* @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
|
|
98
|
-
*/
|
|
99
|
-
invalidateByPrefix(prefix: string): void;
|
|
100
|
-
/**
|
|
101
|
-
* Serializes the current state of the query store into a JSON string.
|
|
102
|
-
* This is used on the server to pass the initial state to the client.
|
|
103
|
-
* @returns A JSON string representing the dehydrated state.
|
|
104
|
-
*/
|
|
105
|
-
dehydrate(): string;
|
|
106
|
-
/**
|
|
107
|
-
* Merges a dehydrated state object into the current store.
|
|
108
|
-
* This is used on the client to hydrate the state received from the server.
|
|
109
|
-
* @param hydratedState - A JSON string from the `dehydrate` method.
|
|
110
|
-
*/
|
|
111
|
-
rehydrate(hydratedState: string): void;
|
|
112
|
-
}
|
|
113
|
-
declare const globalStateManager: GlobalStateManager;
|
|
114
|
-
|
|
115
75
|
/**
|
|
116
76
|
* [نسخة مطورة] يبني سلسلة استعلام (query string) من كائن الخيارات.
|
|
117
77
|
* يدعم الآن الفلاتر المتداخلة (filter[key]=value) والترتيب المتعدد.
|
|
@@ -228,4 +188,4 @@ interface UseApiResourceReturn<T, TCreate, TUpdate, TPathParams> {
|
|
|
228
188
|
setQuery: React.Dispatch<React.SetStateAction<QueryOptions>>;
|
|
229
189
|
}
|
|
230
190
|
|
|
231
|
-
export { ActionConfigModule, ActionOptions,
|
|
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,
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
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,46 +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
|
-
/**
|
|
78
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
79
|
-
*/
|
|
80
|
-
getSnapshot<T>(key: string): ActionStateModule<T>;
|
|
81
|
-
/**
|
|
82
|
-
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
83
|
-
* @returns دالة لإلغاء الاشتراك.
|
|
84
|
-
*/
|
|
85
|
-
subscribe(key: string, callback: () => void): () => void;
|
|
86
|
-
/**
|
|
87
|
-
* يحدّث الحالة لمفتاح معين ويقوم بإعلام جميع المشتركين.
|
|
88
|
-
*/
|
|
89
|
-
setState<T>(key: string, updater: (prevState: ActionStateModule<T>) => ActionStateModule<T>): void;
|
|
90
|
-
/**
|
|
91
|
-
* يجعل البيانات المرتبطة بمفتاح معين "قديمة" (stale).
|
|
92
|
-
*/
|
|
93
|
-
invalidate(key: string): void;
|
|
94
|
-
/**
|
|
95
|
-
* [نسخة محدثة وأكثر قوة]
|
|
96
|
-
* يجعل كل البيانات التي تبدأ بمفتاح معين "قديمة" (stale).
|
|
97
|
-
* @example invalidateByPrefix('myModule/list::') سيبطل كل صفحات القائمة.
|
|
98
|
-
*/
|
|
99
|
-
invalidateByPrefix(prefix: string): void;
|
|
100
|
-
/**
|
|
101
|
-
* Serializes the current state of the query store into a JSON string.
|
|
102
|
-
* This is used on the server to pass the initial state to the client.
|
|
103
|
-
* @returns A JSON string representing the dehydrated state.
|
|
104
|
-
*/
|
|
105
|
-
dehydrate(): string;
|
|
106
|
-
/**
|
|
107
|
-
* Merges a dehydrated state object into the current store.
|
|
108
|
-
* This is used on the client to hydrate the state received from the server.
|
|
109
|
-
* @param hydratedState - A JSON string from the `dehydrate` method.
|
|
110
|
-
*/
|
|
111
|
-
rehydrate(hydratedState: string): void;
|
|
112
|
-
}
|
|
113
|
-
declare const globalStateManager: GlobalStateManager;
|
|
114
|
-
|
|
115
75
|
/**
|
|
116
76
|
* [نسخة مطورة] يبني سلسلة استعلام (query string) من كائن الخيارات.
|
|
117
77
|
* يدعم الآن الفلاتر المتداخلة (filter[key]=value) والترتيب المتعدد.
|
|
@@ -228,4 +188,4 @@ interface UseApiResourceReturn<T, TCreate, TUpdate, TPathParams> {
|
|
|
228
188
|
setQuery: React.Dispatch<React.SetStateAction<QueryOptions>>;
|
|
229
189
|
}
|
|
230
190
|
|
|
231
|
-
export { ActionConfigModule, ActionOptions,
|
|
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
|
@@ -502,11 +502,13 @@ var GlobalStateManager = class {
|
|
|
502
502
|
constructor() {
|
|
503
503
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
504
504
|
}
|
|
505
|
-
/**
|
|
506
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
507
|
-
*/
|
|
508
505
|
getSnapshot(key) {
|
|
509
|
-
|
|
506
|
+
if (!this.store.has(key)) {
|
|
507
|
+
const initialState = createInitialState();
|
|
508
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
509
|
+
return initialState;
|
|
510
|
+
}
|
|
511
|
+
return this.store.get(key).state;
|
|
510
512
|
}
|
|
511
513
|
/**
|
|
512
514
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -647,6 +649,17 @@ var CacheManager = class {
|
|
|
647
649
|
}
|
|
648
650
|
};
|
|
649
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
|
+
};
|
|
650
663
|
export {
|
|
651
664
|
buildPaginateQuery,
|
|
652
665
|
cacheManager,
|
|
@@ -654,6 +667,7 @@ export {
|
|
|
654
667
|
createApiActions,
|
|
655
668
|
createApiClient,
|
|
656
669
|
createApiServices,
|
|
670
|
+
generateCacheKey,
|
|
657
671
|
globalStateManager,
|
|
658
672
|
processResponse
|
|
659
673
|
};
|
package/dist/server.cjs
CHANGED
|
@@ -195,11 +195,13 @@ var GlobalStateManager = class {
|
|
|
195
195
|
constructor() {
|
|
196
196
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
197
197
|
}
|
|
198
|
-
/**
|
|
199
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
200
|
-
*/
|
|
201
198
|
getSnapshot(key) {
|
|
202
|
-
|
|
199
|
+
if (!this.store.has(key)) {
|
|
200
|
+
const initialState = createInitialState();
|
|
201
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
202
|
+
return initialState;
|
|
203
|
+
}
|
|
204
|
+
return this.store.get(key).state;
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
207
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -284,15 +286,94 @@ var GlobalStateManager = class {
|
|
|
284
286
|
};
|
|
285
287
|
var globalStateManager = new GlobalStateManager();
|
|
286
288
|
|
|
287
|
-
// src/
|
|
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
|
|
288
366
|
var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
|
|
289
367
|
const params = { path: callOptions.pathParams, body: input };
|
|
290
368
|
try {
|
|
291
369
|
return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
|
|
292
370
|
} catch (error) {
|
|
371
|
+
console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
|
|
293
372
|
return `${moduleName}/${actionName}::${Date.now()}`;
|
|
294
373
|
}
|
|
295
374
|
};
|
|
375
|
+
|
|
376
|
+
// src/server.ts
|
|
296
377
|
function createServerApi(apiClient, moduleConfig) {
|
|
297
378
|
return {
|
|
298
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-
|
|
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-
|
|
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
|
@@ -161,11 +161,13 @@ var GlobalStateManager = class {
|
|
|
161
161
|
constructor() {
|
|
162
162
|
__publicField(this, "store", /* @__PURE__ */ new Map());
|
|
163
163
|
}
|
|
164
|
-
/**
|
|
165
|
-
* يحصل على لقطة (snapshot) للحالة الحالية لمفتاح معين.
|
|
166
|
-
*/
|
|
167
164
|
getSnapshot(key) {
|
|
168
|
-
|
|
165
|
+
if (!this.store.has(key)) {
|
|
166
|
+
const initialState = createInitialState();
|
|
167
|
+
this.store.set(key, { state: initialState, listeners: /* @__PURE__ */ new Set() });
|
|
168
|
+
return initialState;
|
|
169
|
+
}
|
|
170
|
+
return this.store.get(key).state;
|
|
169
171
|
}
|
|
170
172
|
/**
|
|
171
173
|
* يسجل دالة callback للاستماع إلى التغييرات على مفتاح معين.
|
|
@@ -250,15 +252,94 @@ var GlobalStateManager = class {
|
|
|
250
252
|
};
|
|
251
253
|
var globalStateManager = new GlobalStateManager();
|
|
252
254
|
|
|
253
|
-
// src/
|
|
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
|
|
254
332
|
var generateCacheKey = (moduleName, actionName, input, callOptions = {}) => {
|
|
255
333
|
const params = { path: callOptions.pathParams, body: input };
|
|
256
334
|
try {
|
|
257
335
|
return `${moduleName}/${actionName}::${JSON.stringify(params)}`;
|
|
258
336
|
} catch (error) {
|
|
337
|
+
console.warn("Could not stringify cache key params, falling back to timestamp.", { moduleName, actionName, error });
|
|
259
338
|
return `${moduleName}/${actionName}::${Date.now()}`;
|
|
260
339
|
}
|
|
261
340
|
};
|
|
341
|
+
|
|
342
|
+
// src/server.ts
|
|
262
343
|
function createServerApi(apiClient, moduleConfig) {
|
|
263
344
|
return {
|
|
264
345
|
/**
|