api-core-lib 16.12.134 → 16.12.136
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-DEskFzOY.d.cts → apiModule.types-hGWAkTwf.d.cts} +33 -12
- package/dist/{apiModule.types-DEskFzOY.d.ts → apiModule.types-hGWAkTwf.d.ts} +33 -12
- package/dist/client.cjs +71 -151
- package/dist/client.d.cts +3 -3
- package/dist/client.d.ts +3 -3
- package/dist/client.js +69 -149
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/{useApiRecord.types-C31nzgeP.d.ts → useApiRecord.types-BJop2XPB.d.ts} +1 -1
- package/dist/{useApiRecord.types-mpeiDoxm.d.cts → useApiRecord.types-V-4fiB7L.d.cts} +1 -1
- package/package.json +1 -1
|
@@ -196,10 +196,12 @@ interface t {
|
|
|
196
196
|
payload?: any;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/** @description Extends the base ActionState with an `isStale` flag for automatic refetching. */
|
|
199
200
|
interface ActionState<TOutput> extends ActionStateModule<TOutput> {
|
|
200
201
|
isStale?: boolean;
|
|
201
202
|
}
|
|
202
|
-
|
|
203
|
+
/** @description Defines the configuration for a single API action within a module. */
|
|
204
|
+
interface ActionConfigModule<TInput = unknown, TOutput = unknown> {
|
|
203
205
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
204
206
|
path: string;
|
|
205
207
|
description?: string;
|
|
@@ -213,17 +215,17 @@ interface ActionConfigModule<TInput extends Record<string, any> | undefined = un
|
|
|
213
215
|
_input?: TInput;
|
|
214
216
|
_output?: TOutput;
|
|
215
217
|
}
|
|
218
|
+
/** @description Defines the complete structure of an API module. */
|
|
219
|
+
/**
|
|
220
|
+
* يصف إعدادات موديول API كامل.
|
|
221
|
+
* @template TActions كائن يصف جميع الإجراءات المتاحة في الموديول.
|
|
222
|
+
*/
|
|
216
223
|
interface ApiModuleConfig<TActions extends Record<string, ActionConfigModule<any, any>>> {
|
|
217
224
|
baseEndpoint: string;
|
|
218
225
|
actions: TActions;
|
|
219
226
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
updateUrl: (newSearchParams: string) => void;
|
|
223
|
-
actionsToSync: (keyof TModule['actions'])[];
|
|
224
|
-
defaultSyncAction?: keyof TModule['actions'];
|
|
225
|
-
}
|
|
226
|
-
interface UseApiModuleOptions<TModule extends ApiModuleConfig<any>, TExtra = {}> {
|
|
227
|
+
/** @description Configuration options passed directly to the `useApiModule` hook. */
|
|
228
|
+
interface UseApiModuleOptions<TExtra = {}> {
|
|
227
229
|
onSuccess?: (actionName: string, message: string, data: unknown) => void;
|
|
228
230
|
onError?: (actionName: string, message: string, error?: ApiError | null) => void;
|
|
229
231
|
refetchOnWindowFocus?: boolean;
|
|
@@ -231,12 +233,12 @@ interface UseApiModuleOptions<TModule extends ApiModuleConfig<any>, TExtra = {}>
|
|
|
231
233
|
enabled?: boolean;
|
|
232
234
|
hydratedState?: string;
|
|
233
235
|
extraContextData?: TExtra;
|
|
234
|
-
urlSync?: UrlSyncOptions<TModule>;
|
|
235
|
-
defaultQueryOptions?: Partial<Record<keyof TModule['actions'], QueryOptions>>;
|
|
236
|
-
initialActionsToExecute?: (keyof TModule['actions'])[];
|
|
237
236
|
}
|
|
237
|
+
/** A utility type to infer the Input type (`TInput`) from an ActionConfigModule. */
|
|
238
238
|
type InputOf<TActionConfig> = TActionConfig extends ActionConfigModule<infer TInput, any> ? TInput : never;
|
|
239
|
+
/** A utility type to infer the Output type (`TOutput`) from an ActionConfigModule. */
|
|
239
240
|
type OutputOf<TActionConfig> = TActionConfig extends ActionConfigModule<any, infer TOutput> ? TOutput : never;
|
|
241
|
+
/** @description Defines the options for the `execute` function, enabling optimistic updates. */
|
|
240
242
|
interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
|
|
241
243
|
pathParams?: Record<string, any>;
|
|
242
244
|
config?: AxiosRequestConfig;
|
|
@@ -245,6 +247,7 @@ interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
|
|
|
245
247
|
onError?: (error: ApiError, context?: TContext) => void;
|
|
246
248
|
onSettled?: (data?: TOutput, error?: ApiError, context?: TContext) => void;
|
|
247
249
|
}
|
|
250
|
+
/** @description A fully-typed object representing the callable actions for a module. */
|
|
248
251
|
type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
249
252
|
[K in keyof TActions]: {
|
|
250
253
|
execute: <TContext = unknown>(input?: InputOf<TActions[K]>, options?: ExecuteOptions<InputOf<TActions[K]>, OutputOf<TActions[K]>, TContext>) => Promise<StandardResponse<OutputOf<TActions[K]>>>;
|
|
@@ -253,26 +256,44 @@ type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>
|
|
|
253
256
|
}) => void;
|
|
254
257
|
};
|
|
255
258
|
};
|
|
259
|
+
/** @description A fully-typed object representing the reactive states for each action in a module. */
|
|
256
260
|
type ModuleStates<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
257
261
|
[K in keyof TActions]: ActionState<OutputOf<TActions[K]>>;
|
|
258
262
|
};
|
|
259
263
|
type ActionsWithQuery<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
260
264
|
[K in keyof TActions]: TActions[K] extends ActionConfigModule<QueryOptions, any> ? K : never;
|
|
261
265
|
}[keyof TActions];
|
|
266
|
+
/**
|
|
267
|
+
* يُنشئ نوعًا لكائن `queries` يحتوي فقط على الإجراءات التي تقبل الكويري.
|
|
268
|
+
*/
|
|
262
269
|
type ModuleQueries<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
263
270
|
[K in ActionsWithQuery<TActions>]: UseApiQuery;
|
|
264
271
|
};
|
|
272
|
+
/**
|
|
273
|
+
* @description The complete, fully-typed return object of the `useApiModule` hook.
|
|
274
|
+
*/
|
|
265
275
|
type UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<any, any>>, TExtra extends object = {}> = {
|
|
266
276
|
states: ModuleStates<TActions>;
|
|
267
277
|
actions: ModuleActions<TActions>;
|
|
268
278
|
queries: ModuleQueries<TActions>;
|
|
269
279
|
dehydrate: () => string;
|
|
270
280
|
} & TExtra;
|
|
281
|
+
/**
|
|
282
|
+
* يصف دوال `execute` و `reset` لإجراء واحد.
|
|
283
|
+
* هذا النوع عام (generic) ليتناسب مع أنواع الإدخال والإخراج المختلفة لكل إجراء.
|
|
284
|
+
* @template TAction يمثل إعدادات الإجراء الواحد.
|
|
285
|
+
*/
|
|
271
286
|
type ActionMethods<TAction extends ActionConfigModule<any, any>> = {
|
|
287
|
+
/**
|
|
288
|
+
* الدالة الأساسية لتنفيذ طلب ה-API.
|
|
289
|
+
*/
|
|
272
290
|
execute: <TContext = unknown>(input?: InputOf<TAction>, options?: ExecuteOptions<InputOf<TAction>, OutputOf<TAction>, TContext>) => Promise<StandardResponse<OutputOf<TAction>>>;
|
|
291
|
+
/**
|
|
292
|
+
* دالة لإعادة تعيين حالة إجراء معين في ذاكرة التخزين المؤقت إلى حالته الأولية.
|
|
293
|
+
*/
|
|
273
294
|
reset: (input?: InputOf<TAction>, options?: {
|
|
274
295
|
pathParams?: Record<string, any>;
|
|
275
296
|
}) => void;
|
|
276
297
|
};
|
|
277
298
|
|
|
278
|
-
export type {
|
|
299
|
+
export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, ModuleStates 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, ModuleActions as d, ModuleQueries as e, ApiClientConfig as f, ActionOptions as g, ActionStateModule as h, UseApiQuery as i, ApiError as j, TokenManager as k, MiddlewareContext as l, Middleware as m, RefreshTokenConfig as n, ActionConfig as o, UseApiState as p, ActionState as q, ExecuteOptions as r, ActionsWithQuery as s, t, ActionMethods as u };
|
|
@@ -196,10 +196,12 @@ interface t {
|
|
|
196
196
|
payload?: any;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/** @description Extends the base ActionState with an `isStale` flag for automatic refetching. */
|
|
199
200
|
interface ActionState<TOutput> extends ActionStateModule<TOutput> {
|
|
200
201
|
isStale?: boolean;
|
|
201
202
|
}
|
|
202
|
-
|
|
203
|
+
/** @description Defines the configuration for a single API action within a module. */
|
|
204
|
+
interface ActionConfigModule<TInput = unknown, TOutput = unknown> {
|
|
203
205
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
204
206
|
path: string;
|
|
205
207
|
description?: string;
|
|
@@ -213,17 +215,17 @@ interface ActionConfigModule<TInput extends Record<string, any> | undefined = un
|
|
|
213
215
|
_input?: TInput;
|
|
214
216
|
_output?: TOutput;
|
|
215
217
|
}
|
|
218
|
+
/** @description Defines the complete structure of an API module. */
|
|
219
|
+
/**
|
|
220
|
+
* يصف إعدادات موديول API كامل.
|
|
221
|
+
* @template TActions كائن يصف جميع الإجراءات المتاحة في الموديول.
|
|
222
|
+
*/
|
|
216
223
|
interface ApiModuleConfig<TActions extends Record<string, ActionConfigModule<any, any>>> {
|
|
217
224
|
baseEndpoint: string;
|
|
218
225
|
actions: TActions;
|
|
219
226
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
updateUrl: (newSearchParams: string) => void;
|
|
223
|
-
actionsToSync: (keyof TModule['actions'])[];
|
|
224
|
-
defaultSyncAction?: keyof TModule['actions'];
|
|
225
|
-
}
|
|
226
|
-
interface UseApiModuleOptions<TModule extends ApiModuleConfig<any>, TExtra = {}> {
|
|
227
|
+
/** @description Configuration options passed directly to the `useApiModule` hook. */
|
|
228
|
+
interface UseApiModuleOptions<TExtra = {}> {
|
|
227
229
|
onSuccess?: (actionName: string, message: string, data: unknown) => void;
|
|
228
230
|
onError?: (actionName: string, message: string, error?: ApiError | null) => void;
|
|
229
231
|
refetchOnWindowFocus?: boolean;
|
|
@@ -231,12 +233,12 @@ interface UseApiModuleOptions<TModule extends ApiModuleConfig<any>, TExtra = {}>
|
|
|
231
233
|
enabled?: boolean;
|
|
232
234
|
hydratedState?: string;
|
|
233
235
|
extraContextData?: TExtra;
|
|
234
|
-
urlSync?: UrlSyncOptions<TModule>;
|
|
235
|
-
defaultQueryOptions?: Partial<Record<keyof TModule['actions'], QueryOptions>>;
|
|
236
|
-
initialActionsToExecute?: (keyof TModule['actions'])[];
|
|
237
236
|
}
|
|
237
|
+
/** A utility type to infer the Input type (`TInput`) from an ActionConfigModule. */
|
|
238
238
|
type InputOf<TActionConfig> = TActionConfig extends ActionConfigModule<infer TInput, any> ? TInput : never;
|
|
239
|
+
/** A utility type to infer the Output type (`TOutput`) from an ActionConfigModule. */
|
|
239
240
|
type OutputOf<TActionConfig> = TActionConfig extends ActionConfigModule<any, infer TOutput> ? TOutput : never;
|
|
241
|
+
/** @description Defines the options for the `execute` function, enabling optimistic updates. */
|
|
240
242
|
interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
|
|
241
243
|
pathParams?: Record<string, any>;
|
|
242
244
|
config?: AxiosRequestConfig;
|
|
@@ -245,6 +247,7 @@ interface ExecuteOptions<TInput, TOutput, TContext = unknown> {
|
|
|
245
247
|
onError?: (error: ApiError, context?: TContext) => void;
|
|
246
248
|
onSettled?: (data?: TOutput, error?: ApiError, context?: TContext) => void;
|
|
247
249
|
}
|
|
250
|
+
/** @description A fully-typed object representing the callable actions for a module. */
|
|
248
251
|
type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
249
252
|
[K in keyof TActions]: {
|
|
250
253
|
execute: <TContext = unknown>(input?: InputOf<TActions[K]>, options?: ExecuteOptions<InputOf<TActions[K]>, OutputOf<TActions[K]>, TContext>) => Promise<StandardResponse<OutputOf<TActions[K]>>>;
|
|
@@ -253,26 +256,44 @@ type ModuleActions<TActions extends Record<string, ActionConfigModule<any, any>>
|
|
|
253
256
|
}) => void;
|
|
254
257
|
};
|
|
255
258
|
};
|
|
259
|
+
/** @description A fully-typed object representing the reactive states for each action in a module. */
|
|
256
260
|
type ModuleStates<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
257
261
|
[K in keyof TActions]: ActionState<OutputOf<TActions[K]>>;
|
|
258
262
|
};
|
|
259
263
|
type ActionsWithQuery<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
260
264
|
[K in keyof TActions]: TActions[K] extends ActionConfigModule<QueryOptions, any> ? K : never;
|
|
261
265
|
}[keyof TActions];
|
|
266
|
+
/**
|
|
267
|
+
* يُنشئ نوعًا لكائن `queries` يحتوي فقط على الإجراءات التي تقبل الكويري.
|
|
268
|
+
*/
|
|
262
269
|
type ModuleQueries<TActions extends Record<string, ActionConfigModule<any, any>>> = {
|
|
263
270
|
[K in ActionsWithQuery<TActions>]: UseApiQuery;
|
|
264
271
|
};
|
|
272
|
+
/**
|
|
273
|
+
* @description The complete, fully-typed return object of the `useApiModule` hook.
|
|
274
|
+
*/
|
|
265
275
|
type UseApiModuleReturn<TActions extends Record<string, ActionConfigModule<any, any>>, TExtra extends object = {}> = {
|
|
266
276
|
states: ModuleStates<TActions>;
|
|
267
277
|
actions: ModuleActions<TActions>;
|
|
268
278
|
queries: ModuleQueries<TActions>;
|
|
269
279
|
dehydrate: () => string;
|
|
270
280
|
} & TExtra;
|
|
281
|
+
/**
|
|
282
|
+
* يصف دوال `execute` و `reset` لإجراء واحد.
|
|
283
|
+
* هذا النوع عام (generic) ليتناسب مع أنواع الإدخال والإخراج المختلفة لكل إجراء.
|
|
284
|
+
* @template TAction يمثل إعدادات الإجراء الواحد.
|
|
285
|
+
*/
|
|
271
286
|
type ActionMethods<TAction extends ActionConfigModule<any, any>> = {
|
|
287
|
+
/**
|
|
288
|
+
* الدالة الأساسية لتنفيذ طلب ה-API.
|
|
289
|
+
*/
|
|
272
290
|
execute: <TContext = unknown>(input?: InputOf<TAction>, options?: ExecuteOptions<InputOf<TAction>, OutputOf<TAction>, TContext>) => Promise<StandardResponse<OutputOf<TAction>>>;
|
|
291
|
+
/**
|
|
292
|
+
* دالة لإعادة تعيين حالة إجراء معين في ذاكرة التخزين المؤقت إلى حالته الأولية.
|
|
293
|
+
*/
|
|
273
294
|
reset: (input?: InputOf<TAction>, options?: {
|
|
274
295
|
pathParams?: Record<string, any>;
|
|
275
296
|
}) => void;
|
|
276
297
|
};
|
|
277
298
|
|
|
278
|
-
export type {
|
|
299
|
+
export type { ActionConfigModule as A, ExecutableAction as E, InputOf as I, LogLevel as L, ModuleStates 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, ModuleActions as d, ModuleQueries as e, ApiClientConfig as f, ActionOptions as g, ActionStateModule as h, UseApiQuery as i, ApiError as j, TokenManager as k, MiddlewareContext as l, Middleware as m, RefreshTokenConfig as n, ActionConfig as o, UseApiState as p, ActionState as q, ExecuteOptions as r, ActionsWithQuery as s, t, ActionMethods as u };
|
package/dist/client.cjs
CHANGED
|
@@ -279,8 +279,7 @@ var ApiModuleProvider = ApiModuleContext.Provider;
|
|
|
279
279
|
var createInitialState = () => ({
|
|
280
280
|
data: null,
|
|
281
281
|
lastSuccessAt: void 0,
|
|
282
|
-
meta:
|
|
283
|
-
links: void 0,
|
|
282
|
+
meta: [],
|
|
284
283
|
validationErrors: [],
|
|
285
284
|
error: null,
|
|
286
285
|
loading: false,
|
|
@@ -322,117 +321,40 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
322
321
|
refetchOnWindowFocus = true,
|
|
323
322
|
onSuccess,
|
|
324
323
|
onError,
|
|
325
|
-
pathParams:
|
|
324
|
+
pathParams: modulePathParams,
|
|
326
325
|
enabled = true,
|
|
327
326
|
hydratedState,
|
|
328
|
-
extraContextData
|
|
329
|
-
urlSync,
|
|
330
|
-
defaultQueryOptions,
|
|
331
|
-
initialActionsToExecute
|
|
327
|
+
extraContextData
|
|
332
328
|
} = options;
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const actionConfig = moduleConfig.actions[actionName];
|
|
337
|
-
if (actionConfig.hasQuery) {
|
|
338
|
-
initialOptions[actionName] = { ..._optionalChain([defaultQueryOptions, 'optionalAccess', _6 => _6[actionName]]) || {} };
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return initialOptions;
|
|
342
|
-
});
|
|
343
|
-
const queryOptionsRef = _react.useRef.call(void 0, queryOptions);
|
|
344
|
-
const pathParamsRef = _react.useRef.call(void 0, globalPathParams);
|
|
345
|
-
const savedCallbacksRef = _react.useRef.call(void 0, { onSuccess, onError });
|
|
346
|
-
_react.useEffect.call(void 0, () => {
|
|
347
|
-
queryOptionsRef.current = queryOptions;
|
|
348
|
-
}, [queryOptions]);
|
|
329
|
+
const pathParamsString = _react.useMemo.call(void 0, () => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
330
|
+
const [queryOptions, setQueryOptions] = _react.useState.call(void 0, {});
|
|
331
|
+
const savedCallbacks = _react.useRef.call(void 0, { onSuccess, onError });
|
|
349
332
|
_react.useEffect.call(void 0, () => {
|
|
350
|
-
|
|
351
|
-
}, [globalPathParams]);
|
|
352
|
-
_react.useEffect.call(void 0, () => {
|
|
353
|
-
savedCallbacksRef.current = { onSuccess, onError };
|
|
333
|
+
savedCallbacks.current = { onSuccess, onError };
|
|
354
334
|
}, [onSuccess, onError]);
|
|
355
|
-
|
|
356
|
-
_react.useEffect.call(void 0, () => {
|
|
335
|
+
_react.useMemo.call(void 0, () => {
|
|
357
336
|
if (hydratedState) {
|
|
358
337
|
_chunkJAMEOM7Tcjs.globalStateManager.rehydrate(hydratedState);
|
|
359
338
|
}
|
|
360
339
|
}, [hydratedState]);
|
|
361
|
-
_react.
|
|
362
|
-
|
|
363
|
-
const { searchParams, actionsToSync, defaultSyncAction } = urlSync;
|
|
364
|
-
const params = new URLSearchParams(searchParams);
|
|
365
|
-
const queryFromUrl = {};
|
|
366
|
-
params.forEach((value, key) => {
|
|
367
|
-
const parts = key.split(".");
|
|
368
|
-
const hasPrefix = parts.length > 1;
|
|
369
|
-
const actionName = hasPrefix ? parts[0] : defaultSyncAction;
|
|
370
|
-
const paramKey = hasPrefix ? parts[1] : parts[0];
|
|
371
|
-
if (actionName && paramKey && actionsToSync.some((a) => a === actionName)) {
|
|
372
|
-
if (!queryFromUrl[actionName]) queryFromUrl[actionName] = {};
|
|
373
|
-
const isNum = !isNaN(Number(value)) && value.trim() !== "";
|
|
374
|
-
queryFromUrl[actionName][paramKey] = isNum ? Number(value) : value;
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
if (Object.keys(queryFromUrl).length > 0) {
|
|
378
|
-
setQueryOptions((prev) => {
|
|
379
|
-
const newState = { ...prev };
|
|
380
|
-
for (const actionName in queryFromUrl) {
|
|
381
|
-
newState[actionName] = { ...newState[actionName], ...queryFromUrl[actionName] };
|
|
382
|
-
}
|
|
383
|
-
return newState;
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}, [_optionalChain([urlSync, 'optionalAccess', _7 => _7.searchParams]), _optionalChain([urlSync, 'optionalAccess', _8 => _8.actionsToSync]), _optionalChain([urlSync, 'optionalAccess', _9 => _9.defaultSyncAction])]);
|
|
387
|
-
_react.useEffect.call(void 0, () => {
|
|
388
|
-
if (!urlSync) return;
|
|
389
|
-
const { searchParams, updateUrl, actionsToSync, defaultSyncAction } = urlSync;
|
|
390
|
-
const currentParams = new URLSearchParams(searchParams);
|
|
391
|
-
let hasChanged = false;
|
|
392
|
-
for (const actionName in queryOptions) {
|
|
393
|
-
if (actionsToSync.some((a) => a === actionName)) {
|
|
394
|
-
const params = queryOptions[actionName];
|
|
395
|
-
const isDefaultAction = actionName === defaultSyncAction;
|
|
396
|
-
for (const key in params) {
|
|
397
|
-
const fullKey = isDefaultAction ? key : `${actionName}.${key}`;
|
|
398
|
-
const value = params[key];
|
|
399
|
-
const stringValue = value !== void 0 && value !== null ? String(value) : "";
|
|
400
|
-
if (currentParams.get(fullKey) !== stringValue) {
|
|
401
|
-
if (stringValue) currentParams.set(fullKey, stringValue);
|
|
402
|
-
else currentParams.delete(fullKey);
|
|
403
|
-
hasChanged = true;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (hasChanged) {
|
|
409
|
-
updateUrl(currentParams.toString());
|
|
410
|
-
}
|
|
411
|
-
}, [queryOptions, _optionalChain([urlSync, 'optionalAccess', _10 => _10.updateUrl]), _optionalChain([urlSync, 'optionalAccess', _11 => _11.searchParams]), _optionalChain([urlSync, 'optionalAccess', _12 => _12.actionsToSync]), _optionalChain([urlSync, 'optionalAccess', _13 => _13.defaultSyncAction])]);
|
|
412
|
-
_react.useMemo.call(void 0, () => {
|
|
413
|
-
for (const actionName in moduleConfig.actions) {
|
|
340
|
+
const actions = _react.useMemo.call(void 0, () => {
|
|
341
|
+
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
414
342
|
const actionConfig = moduleConfig.actions[actionName];
|
|
415
343
|
const shouldCache = actionConfig.cacheResponse !== false;
|
|
416
344
|
const execute = async (input, options2 = {}) => {
|
|
417
|
-
const finalPathParams = { ...
|
|
418
|
-
const
|
|
419
|
-
let
|
|
420
|
-
if (actionConfig.method === "GET" && actionConfig.hasQuery) {
|
|
421
|
-
bodyForCall = { ...currentQueryOptions, ..._optionalChain([options2, 'access', _14 => _14.config, 'optionalAccess', _15 => _15.params]), ...input };
|
|
422
|
-
} else if (actionConfig.upload && input) {
|
|
423
|
-
bodyForCall = new FormData();
|
|
424
|
-
for (const key in input) {
|
|
425
|
-
bodyForCall.append(key, input[key]);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
const cacheKey = shouldCache ? _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0, moduleConfig.baseEndpoint, actionName, bodyForCall, { pathParams: finalPathParams }) : "";
|
|
429
|
-
if (shouldCache) {
|
|
430
|
-
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
|
|
431
|
-
}
|
|
345
|
+
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
346
|
+
const cacheKey = shouldCache ? _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0, moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
|
|
347
|
+
let mutationContext;
|
|
432
348
|
try {
|
|
349
|
+
if (options2.onMutate && shouldCache) {
|
|
350
|
+
mutationContext = await options2.onMutate(input);
|
|
351
|
+
}
|
|
352
|
+
if (shouldCache) {
|
|
353
|
+
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
|
|
354
|
+
}
|
|
433
355
|
const result = await _chunkJAMEOM7Tcjs.callDynamicApi.call(void 0, axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
|
|
434
356
|
pathParams: finalPathParams,
|
|
435
|
-
body:
|
|
357
|
+
body: input,
|
|
436
358
|
config: options2.config
|
|
437
359
|
});
|
|
438
360
|
if (shouldCache) {
|
|
@@ -446,69 +368,57 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
446
368
|
links: result.links,
|
|
447
369
|
message: result.message,
|
|
448
370
|
validationErrors: result.validationErrors || [],
|
|
449
|
-
rawResponse: result.rawResponse
|
|
450
|
-
lastSuccessAt: result.success ? Date.now() : prev.lastSuccessAt
|
|
371
|
+
rawResponse: result.rawResponse
|
|
451
372
|
}));
|
|
452
373
|
}
|
|
453
374
|
if (result.success) {
|
|
454
|
-
_optionalChain([
|
|
455
|
-
_optionalChain([options2, 'access',
|
|
456
|
-
_optionalChain([actionConfig, 'access',
|
|
375
|
+
_optionalChain([savedCallbacks, 'access', _6 => _6.current, 'access', _7 => _7.onSuccess, 'optionalCall', _8 => _8(actionName, result.message || "Action successful", result.data)]);
|
|
376
|
+
_optionalChain([options2, 'access', _9 => _9.onSuccess, 'optionalCall', _10 => _10(result.data, mutationContext)]);
|
|
377
|
+
_optionalChain([actionConfig, 'access', _11 => _11.invalidates, 'optionalAccess', _12 => _12.forEach, 'call', _13 => _13((keyToInvalidate) => {
|
|
457
378
|
const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
|
|
458
379
|
_chunkJAMEOM7Tcjs.globalStateManager.invalidateByPrefix(prefix);
|
|
459
380
|
})]);
|
|
460
381
|
} else {
|
|
461
|
-
_optionalChain([
|
|
462
|
-
_optionalChain([options2, 'access',
|
|
382
|
+
_optionalChain([savedCallbacks, 'access', _14 => _14.current, 'access', _15 => _15.onError, 'optionalCall', _16 => _16(actionName, result.message || "Action failed", _nullishCoalesce(result.error, () => ( void 0)))]);
|
|
383
|
+
_optionalChain([options2, 'access', _17 => _17.onError, 'optionalCall', _18 => _18(result.error, mutationContext)]);
|
|
463
384
|
}
|
|
464
385
|
return result;
|
|
465
386
|
} catch (error) {
|
|
466
|
-
const apiError = _optionalChain([error, 'access',
|
|
387
|
+
const apiError = _optionalChain([error, 'access', _19 => _19.response, 'optionalAccess', _20 => _20.data]) || { status: 500, message: error.message };
|
|
467
388
|
if (shouldCache) {
|
|
468
389
|
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
|
|
469
390
|
}
|
|
470
|
-
_optionalChain([
|
|
471
|
-
_optionalChain([options2, 'access',
|
|
391
|
+
_optionalChain([savedCallbacks, 'access', _21 => _21.current, 'access', _22 => _22.onError, 'optionalCall', _23 => _23(actionName, apiError.message, apiError)]);
|
|
392
|
+
_optionalChain([options2, 'access', _24 => _24.onError, 'optionalCall', _25 => _25(apiError, mutationContext)]);
|
|
472
393
|
throw error;
|
|
394
|
+
} finally {
|
|
395
|
+
if (options2.onSettled) {
|
|
396
|
+
options2.onSettled();
|
|
397
|
+
}
|
|
473
398
|
}
|
|
474
399
|
};
|
|
475
400
|
const reset = (input, options2 = {}) => {
|
|
476
401
|
if (shouldCache) {
|
|
477
|
-
const finalPathParams = { ...
|
|
402
|
+
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
478
403
|
const cacheKey = _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0, moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
|
|
479
404
|
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, () => createInitialState());
|
|
480
405
|
}
|
|
481
406
|
};
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const initialFetchRef = _react.useRef.call(void 0, false);
|
|
487
|
-
_react.useEffect.call(void 0, () => {
|
|
488
|
-
if (typeof window === "undefined" || initialFetchRef.current || !enabled) return;
|
|
489
|
-
const actionsToRun = initialActionsToExecute ? initialActionsToExecute.map(String) : Object.keys(moduleConfig.actions).filter(
|
|
490
|
-
(actionName) => moduleConfig.actions[actionName].autoFetch
|
|
491
|
-
);
|
|
492
|
-
actionsToRun.forEach((actionName) => {
|
|
493
|
-
const key = actionName;
|
|
494
|
-
const executeAction = _optionalChain([actions, 'access', _36 => _36[key], 'optionalAccess', _37 => _37.execute]);
|
|
495
|
-
if (typeof executeAction === "function") {
|
|
496
|
-
executeAction();
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
initialFetchRef.current = true;
|
|
500
|
-
}, [actions, initialActionsToExecute, moduleConfig.actions, enabled]);
|
|
407
|
+
acc[actionName] = { execute, reset };
|
|
408
|
+
return acc;
|
|
409
|
+
}, {});
|
|
410
|
+
}, [axiosInstance, moduleConfig, pathParamsString]);
|
|
501
411
|
const queries = _react.useMemo.call(void 0, () => {
|
|
502
412
|
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
503
413
|
const actionConfig = moduleConfig.actions[actionName];
|
|
504
|
-
if (_optionalChain([actionConfig, 'optionalAccess',
|
|
414
|
+
if (_optionalChain([actionConfig, 'optionalAccess', _26 => _26.hasQuery])) {
|
|
505
415
|
const setActionQueryOptions = (updater) => {
|
|
506
416
|
const key = actionName;
|
|
507
417
|
setQueryOptions((prev) => ({ ...prev, [key]: typeof updater === "function" ? updater(prev[key] || {}) : updater }));
|
|
508
418
|
};
|
|
419
|
+
const specificActionExecute = actions[actionName].execute;
|
|
509
420
|
const refetch = () => {
|
|
510
|
-
|
|
511
|
-
execute(queryOptions[actionName] || {});
|
|
421
|
+
specificActionExecute(queryOptions[actionName] || {});
|
|
512
422
|
};
|
|
513
423
|
acc[actionName] = {
|
|
514
424
|
options: queryOptions[actionName] || {},
|
|
@@ -520,29 +430,39 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
520
430
|
setFilters: (filter) => setActionQueryOptions((p) => ({ ...p, filter, page: 1 })),
|
|
521
431
|
setSorting: (sortBy) => setActionQueryOptions((p) => ({ ...p, sortBy })),
|
|
522
432
|
setQueryParam: (key, value) => setActionQueryOptions((p) => ({ ...p, [key]: value, page: key !== "page" ? value : p.page })),
|
|
523
|
-
reset: () => setActionQueryOptions(
|
|
433
|
+
reset: () => setActionQueryOptions({})
|
|
524
434
|
};
|
|
525
435
|
}
|
|
526
436
|
return acc;
|
|
527
437
|
}, {});
|
|
528
|
-
}, [actions, queryOptions, moduleConfig.actions
|
|
438
|
+
}, [actions, queryOptions, moduleConfig.actions]);
|
|
529
439
|
const states = {};
|
|
530
440
|
function isActionWithQuery(key, actions2) {
|
|
531
|
-
return _optionalChain([actions2, 'access',
|
|
441
|
+
return _optionalChain([actions2, 'access', _27 => _27[key], 'optionalAccess', _28 => _28.hasQuery]) === true;
|
|
532
442
|
}
|
|
533
443
|
for (const actionName in moduleConfig.actions) {
|
|
534
444
|
if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
|
|
535
|
-
const
|
|
536
|
-
const actionConfig = moduleConfig.actions[key];
|
|
445
|
+
const actionConfig = moduleConfig.actions[actionName];
|
|
537
446
|
if (actionConfig.cacheResponse !== false) {
|
|
538
447
|
let currentQueryOptions;
|
|
539
|
-
if (isActionWithQuery(
|
|
540
|
-
currentQueryOptions = _optionalChain([queries, 'access',
|
|
448
|
+
if (isActionWithQuery(actionName, moduleConfig.actions)) {
|
|
449
|
+
currentQueryOptions = _optionalChain([queries, 'access', _29 => _29[actionName], 'optionalAccess', _30 => _30.options]);
|
|
541
450
|
}
|
|
542
451
|
const input = currentQueryOptions;
|
|
543
|
-
const pathParams =
|
|
544
|
-
const cacheKey = _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0,
|
|
545
|
-
|
|
452
|
+
const pathParams = JSON.parse(pathParamsString);
|
|
453
|
+
const cacheKey = _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0,
|
|
454
|
+
moduleConfig.baseEndpoint,
|
|
455
|
+
actionName,
|
|
456
|
+
input,
|
|
457
|
+
{ pathParams }
|
|
458
|
+
);
|
|
459
|
+
states[actionName] = useApiActionState(
|
|
460
|
+
actionConfig,
|
|
461
|
+
cacheKey,
|
|
462
|
+
actions[actionName].execute,
|
|
463
|
+
input,
|
|
464
|
+
enabled
|
|
465
|
+
);
|
|
546
466
|
} else {
|
|
547
467
|
states[actionName] = createInitialState();
|
|
548
468
|
}
|
|
@@ -553,10 +473,12 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
553
473
|
if (!enabled || !refetchOnWindowFocus) return;
|
|
554
474
|
const onFocus = () => {
|
|
555
475
|
if (Date.now() - lastBlurTimestamp.current > 1e4) {
|
|
556
|
-
|
|
476
|
+
const actionKeys = Object.keys(moduleConfig.actions);
|
|
477
|
+
for (const actionName of actionKeys) {
|
|
557
478
|
const state = states[actionName];
|
|
558
479
|
if (state && state.called && !state.loading) {
|
|
559
|
-
|
|
480
|
+
const prefix = `${moduleConfig.baseEndpoint}/${actionName}::`;
|
|
481
|
+
_chunkJAMEOM7Tcjs.globalStateManager.invalidateByPrefix(prefix);
|
|
560
482
|
}
|
|
561
483
|
}
|
|
562
484
|
}
|
|
@@ -571,16 +493,14 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
571
493
|
window.removeEventListener("blur", onBlur);
|
|
572
494
|
};
|
|
573
495
|
}, [enabled, refetchOnWindowFocus, moduleConfig, states]);
|
|
574
|
-
const dehydrate = _react.
|
|
496
|
+
const dehydrate = _react.useMemo.call(void 0, () => {
|
|
497
|
+
return () => _chunkJAMEOM7Tcjs.globalStateManager.dehydrate();
|
|
498
|
+
}, []);
|
|
499
|
+
const baseApiReturn = { actions, states, queries, dehydrate };
|
|
575
500
|
const finalApiReturn = _react.useMemo.call(void 0, () => ({
|
|
576
|
-
|
|
577
|
-
states,
|
|
578
|
-
queries,
|
|
579
|
-
dehydrate,
|
|
501
|
+
...baseApiReturn,
|
|
580
502
|
...extraContextData || {}
|
|
581
|
-
|
|
582
|
-
// `actions` is stable and doesn't need to be a dependency.
|
|
583
|
-
}), [actions, states, queries, dehydrate, extraContextData]);
|
|
503
|
+
}), [baseApiReturn, extraContextData]);
|
|
584
504
|
return finalApiReturn;
|
|
585
505
|
}
|
|
586
506
|
|
package/dist/client.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { U as UseApiConfig, A as
|
|
3
|
-
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-
|
|
2
|
+
import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, M as ModuleStates, d as ModuleActions, e as ModuleQueries } from './apiModule.types-hGWAkTwf.cjs';
|
|
3
|
+
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-V-4fiB7L.cjs';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode } from 'react';
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ declare const ApiModuleProvider: react.Provider<{
|
|
|
28
28
|
queries: ModuleQueries<any>;
|
|
29
29
|
dehydrate: () => string;
|
|
30
30
|
} | null>;
|
|
31
|
-
declare function useApiModule<
|
|
31
|
+
declare function useApiModule<TActions extends Record<string, ActionConfigModule<any, any>>, TExtra extends object = {}>(axiosInstance: AxiosInstance, moduleConfig: ApiModuleConfig<TActions>, options?: UseApiModuleOptions<TExtra>): UseApiModuleReturn<TActions, TExtra>;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Creates a strongly-typed React Context, Provider, and consumer hook for a specific API module.
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import { U as UseApiConfig, A as
|
|
3
|
-
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-
|
|
2
|
+
import { U as UseApiConfig, A as ActionConfigModule, a as ApiModuleConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, M as ModuleStates, d as ModuleActions, e as ModuleQueries } from './apiModule.types-hGWAkTwf.js';
|
|
3
|
+
import { U as UseApiRecordConfig, a as UseApiRecordReturn } from './useApiRecord.types-BJop2XPB.js';
|
|
4
4
|
import * as react from 'react';
|
|
5
5
|
import { ReactNode } from 'react';
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ declare const ApiModuleProvider: react.Provider<{
|
|
|
28
28
|
queries: ModuleQueries<any>;
|
|
29
29
|
dehydrate: () => string;
|
|
30
30
|
} | null>;
|
|
31
|
-
declare function useApiModule<
|
|
31
|
+
declare function useApiModule<TActions extends Record<string, ActionConfigModule<any, any>>, TExtra extends object = {}>(axiosInstance: AxiosInstance, moduleConfig: ApiModuleConfig<TActions>, options?: UseApiModuleOptions<TExtra>): UseApiModuleReturn<TActions, TExtra>;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* Creates a strongly-typed React Context, Provider, and consumer hook for a specific API module.
|
package/dist/client.js
CHANGED
|
@@ -279,8 +279,7 @@ var ApiModuleProvider = ApiModuleContext.Provider;
|
|
|
279
279
|
var createInitialState = () => ({
|
|
280
280
|
data: null,
|
|
281
281
|
lastSuccessAt: void 0,
|
|
282
|
-
meta:
|
|
283
|
-
links: void 0,
|
|
282
|
+
meta: [],
|
|
284
283
|
validationErrors: [],
|
|
285
284
|
error: null,
|
|
286
285
|
loading: false,
|
|
@@ -322,117 +321,40 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
322
321
|
refetchOnWindowFocus = true,
|
|
323
322
|
onSuccess,
|
|
324
323
|
onError,
|
|
325
|
-
pathParams:
|
|
324
|
+
pathParams: modulePathParams,
|
|
326
325
|
enabled = true,
|
|
327
326
|
hydratedState,
|
|
328
|
-
extraContextData
|
|
329
|
-
urlSync,
|
|
330
|
-
defaultQueryOptions,
|
|
331
|
-
initialActionsToExecute
|
|
327
|
+
extraContextData
|
|
332
328
|
} = options;
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const actionConfig = moduleConfig.actions[actionName];
|
|
337
|
-
if (actionConfig.hasQuery) {
|
|
338
|
-
initialOptions[actionName] = { ...defaultQueryOptions?.[actionName] || {} };
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return initialOptions;
|
|
342
|
-
});
|
|
343
|
-
const queryOptionsRef = useRef4(queryOptions);
|
|
344
|
-
const pathParamsRef = useRef4(globalPathParams);
|
|
345
|
-
const savedCallbacksRef = useRef4({ onSuccess, onError });
|
|
346
|
-
useEffect4(() => {
|
|
347
|
-
queryOptionsRef.current = queryOptions;
|
|
348
|
-
}, [queryOptions]);
|
|
329
|
+
const pathParamsString = useMemo3(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
330
|
+
const [queryOptions, setQueryOptions] = useState3({});
|
|
331
|
+
const savedCallbacks = useRef4({ onSuccess, onError });
|
|
349
332
|
useEffect4(() => {
|
|
350
|
-
|
|
351
|
-
}, [globalPathParams]);
|
|
352
|
-
useEffect4(() => {
|
|
353
|
-
savedCallbacksRef.current = { onSuccess, onError };
|
|
333
|
+
savedCallbacks.current = { onSuccess, onError };
|
|
354
334
|
}, [onSuccess, onError]);
|
|
355
|
-
|
|
356
|
-
useEffect4(() => {
|
|
335
|
+
useMemo3(() => {
|
|
357
336
|
if (hydratedState) {
|
|
358
337
|
globalStateManager.rehydrate(hydratedState);
|
|
359
338
|
}
|
|
360
339
|
}, [hydratedState]);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
const { searchParams, actionsToSync, defaultSyncAction } = urlSync;
|
|
364
|
-
const params = new URLSearchParams(searchParams);
|
|
365
|
-
const queryFromUrl = {};
|
|
366
|
-
params.forEach((value, key) => {
|
|
367
|
-
const parts = key.split(".");
|
|
368
|
-
const hasPrefix = parts.length > 1;
|
|
369
|
-
const actionName = hasPrefix ? parts[0] : defaultSyncAction;
|
|
370
|
-
const paramKey = hasPrefix ? parts[1] : parts[0];
|
|
371
|
-
if (actionName && paramKey && actionsToSync.some((a) => a === actionName)) {
|
|
372
|
-
if (!queryFromUrl[actionName]) queryFromUrl[actionName] = {};
|
|
373
|
-
const isNum = !isNaN(Number(value)) && value.trim() !== "";
|
|
374
|
-
queryFromUrl[actionName][paramKey] = isNum ? Number(value) : value;
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
if (Object.keys(queryFromUrl).length > 0) {
|
|
378
|
-
setQueryOptions((prev) => {
|
|
379
|
-
const newState = { ...prev };
|
|
380
|
-
for (const actionName in queryFromUrl) {
|
|
381
|
-
newState[actionName] = { ...newState[actionName], ...queryFromUrl[actionName] };
|
|
382
|
-
}
|
|
383
|
-
return newState;
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}, [urlSync?.searchParams, urlSync?.actionsToSync, urlSync?.defaultSyncAction]);
|
|
387
|
-
useEffect4(() => {
|
|
388
|
-
if (!urlSync) return;
|
|
389
|
-
const { searchParams, updateUrl, actionsToSync, defaultSyncAction } = urlSync;
|
|
390
|
-
const currentParams = new URLSearchParams(searchParams);
|
|
391
|
-
let hasChanged = false;
|
|
392
|
-
for (const actionName in queryOptions) {
|
|
393
|
-
if (actionsToSync.some((a) => a === actionName)) {
|
|
394
|
-
const params = queryOptions[actionName];
|
|
395
|
-
const isDefaultAction = actionName === defaultSyncAction;
|
|
396
|
-
for (const key in params) {
|
|
397
|
-
const fullKey = isDefaultAction ? key : `${actionName}.${key}`;
|
|
398
|
-
const value = params[key];
|
|
399
|
-
const stringValue = value !== void 0 && value !== null ? String(value) : "";
|
|
400
|
-
if (currentParams.get(fullKey) !== stringValue) {
|
|
401
|
-
if (stringValue) currentParams.set(fullKey, stringValue);
|
|
402
|
-
else currentParams.delete(fullKey);
|
|
403
|
-
hasChanged = true;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
if (hasChanged) {
|
|
409
|
-
updateUrl(currentParams.toString());
|
|
410
|
-
}
|
|
411
|
-
}, [queryOptions, urlSync?.updateUrl, urlSync?.searchParams, urlSync?.actionsToSync, urlSync?.defaultSyncAction]);
|
|
412
|
-
useMemo3(() => {
|
|
413
|
-
for (const actionName in moduleConfig.actions) {
|
|
340
|
+
const actions = useMemo3(() => {
|
|
341
|
+
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
414
342
|
const actionConfig = moduleConfig.actions[actionName];
|
|
415
343
|
const shouldCache = actionConfig.cacheResponse !== false;
|
|
416
344
|
const execute = async (input, options2 = {}) => {
|
|
417
|
-
const finalPathParams = { ...
|
|
418
|
-
const
|
|
419
|
-
let
|
|
420
|
-
if (actionConfig.method === "GET" && actionConfig.hasQuery) {
|
|
421
|
-
bodyForCall = { ...currentQueryOptions, ...options2.config?.params, ...input };
|
|
422
|
-
} else if (actionConfig.upload && input) {
|
|
423
|
-
bodyForCall = new FormData();
|
|
424
|
-
for (const key in input) {
|
|
425
|
-
bodyForCall.append(key, input[key]);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, bodyForCall, { pathParams: finalPathParams }) : "";
|
|
429
|
-
if (shouldCache) {
|
|
430
|
-
globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
|
|
431
|
-
}
|
|
345
|
+
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
346
|
+
const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
|
|
347
|
+
let mutationContext;
|
|
432
348
|
try {
|
|
349
|
+
if (options2.onMutate && shouldCache) {
|
|
350
|
+
mutationContext = await options2.onMutate(input);
|
|
351
|
+
}
|
|
352
|
+
if (shouldCache) {
|
|
353
|
+
globalStateManager.setState(cacheKey, (prev) => ({ ...prev, loading: true, called: true, error: null, isStale: false }));
|
|
354
|
+
}
|
|
433
355
|
const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
|
|
434
356
|
pathParams: finalPathParams,
|
|
435
|
-
body:
|
|
357
|
+
body: input,
|
|
436
358
|
config: options2.config
|
|
437
359
|
});
|
|
438
360
|
if (shouldCache) {
|
|
@@ -446,20 +368,19 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
446
368
|
links: result.links,
|
|
447
369
|
message: result.message,
|
|
448
370
|
validationErrors: result.validationErrors || [],
|
|
449
|
-
rawResponse: result.rawResponse
|
|
450
|
-
lastSuccessAt: result.success ? Date.now() : prev.lastSuccessAt
|
|
371
|
+
rawResponse: result.rawResponse
|
|
451
372
|
}));
|
|
452
373
|
}
|
|
453
374
|
if (result.success) {
|
|
454
|
-
|
|
455
|
-
options2.onSuccess?.(result.data,
|
|
375
|
+
savedCallbacks.current.onSuccess?.(actionName, result.message || "Action successful", result.data);
|
|
376
|
+
options2.onSuccess?.(result.data, mutationContext);
|
|
456
377
|
actionConfig.invalidates?.forEach((keyToInvalidate) => {
|
|
457
378
|
const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
|
|
458
379
|
globalStateManager.invalidateByPrefix(prefix);
|
|
459
380
|
});
|
|
460
381
|
} else {
|
|
461
|
-
|
|
462
|
-
options2.onError?.(result.error,
|
|
382
|
+
savedCallbacks.current.onError?.(actionName, result.message || "Action failed", result.error ?? void 0);
|
|
383
|
+
options2.onError?.(result.error, mutationContext);
|
|
463
384
|
}
|
|
464
385
|
return result;
|
|
465
386
|
} catch (error) {
|
|
@@ -467,37 +388,26 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
467
388
|
if (shouldCache) {
|
|
468
389
|
globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
|
|
469
390
|
}
|
|
470
|
-
|
|
471
|
-
options2.onError?.(apiError,
|
|
391
|
+
savedCallbacks.current.onError?.(actionName, apiError.message, apiError);
|
|
392
|
+
options2.onError?.(apiError, mutationContext);
|
|
472
393
|
throw error;
|
|
394
|
+
} finally {
|
|
395
|
+
if (options2.onSettled) {
|
|
396
|
+
options2.onSettled();
|
|
397
|
+
}
|
|
473
398
|
}
|
|
474
399
|
};
|
|
475
400
|
const reset = (input, options2 = {}) => {
|
|
476
401
|
if (shouldCache) {
|
|
477
|
-
const finalPathParams = { ...
|
|
402
|
+
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
478
403
|
const cacheKey = generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams });
|
|
479
404
|
globalStateManager.setState(cacheKey, () => createInitialState());
|
|
480
405
|
}
|
|
481
406
|
};
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const initialFetchRef = useRef4(false);
|
|
487
|
-
useEffect4(() => {
|
|
488
|
-
if (typeof window === "undefined" || initialFetchRef.current || !enabled) return;
|
|
489
|
-
const actionsToRun = initialActionsToExecute ? initialActionsToExecute.map(String) : Object.keys(moduleConfig.actions).filter(
|
|
490
|
-
(actionName) => moduleConfig.actions[actionName].autoFetch
|
|
491
|
-
);
|
|
492
|
-
actionsToRun.forEach((actionName) => {
|
|
493
|
-
const key = actionName;
|
|
494
|
-
const executeAction = actions[key]?.execute;
|
|
495
|
-
if (typeof executeAction === "function") {
|
|
496
|
-
executeAction();
|
|
497
|
-
}
|
|
498
|
-
});
|
|
499
|
-
initialFetchRef.current = true;
|
|
500
|
-
}, [actions, initialActionsToExecute, moduleConfig.actions, enabled]);
|
|
407
|
+
acc[actionName] = { execute, reset };
|
|
408
|
+
return acc;
|
|
409
|
+
}, {});
|
|
410
|
+
}, [axiosInstance, moduleConfig, pathParamsString]);
|
|
501
411
|
const queries = useMemo3(() => {
|
|
502
412
|
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
503
413
|
const actionConfig = moduleConfig.actions[actionName];
|
|
@@ -506,9 +416,9 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
506
416
|
const key = actionName;
|
|
507
417
|
setQueryOptions((prev) => ({ ...prev, [key]: typeof updater === "function" ? updater(prev[key] || {}) : updater }));
|
|
508
418
|
};
|
|
419
|
+
const specificActionExecute = actions[actionName].execute;
|
|
509
420
|
const refetch = () => {
|
|
510
|
-
|
|
511
|
-
execute(queryOptions[actionName] || {});
|
|
421
|
+
specificActionExecute(queryOptions[actionName] || {});
|
|
512
422
|
};
|
|
513
423
|
acc[actionName] = {
|
|
514
424
|
options: queryOptions[actionName] || {},
|
|
@@ -520,29 +430,39 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
520
430
|
setFilters: (filter) => setActionQueryOptions((p) => ({ ...p, filter, page: 1 })),
|
|
521
431
|
setSorting: (sortBy) => setActionQueryOptions((p) => ({ ...p, sortBy })),
|
|
522
432
|
setQueryParam: (key, value) => setActionQueryOptions((p) => ({ ...p, [key]: value, page: key !== "page" ? value : p.page })),
|
|
523
|
-
reset: () => setActionQueryOptions(
|
|
433
|
+
reset: () => setActionQueryOptions({})
|
|
524
434
|
};
|
|
525
435
|
}
|
|
526
436
|
return acc;
|
|
527
437
|
}, {});
|
|
528
|
-
}, [actions, queryOptions, moduleConfig.actions
|
|
438
|
+
}, [actions, queryOptions, moduleConfig.actions]);
|
|
529
439
|
const states = {};
|
|
530
440
|
function isActionWithQuery(key, actions2) {
|
|
531
441
|
return actions2[key]?.hasQuery === true;
|
|
532
442
|
}
|
|
533
443
|
for (const actionName in moduleConfig.actions) {
|
|
534
444
|
if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
|
|
535
|
-
const
|
|
536
|
-
const actionConfig = moduleConfig.actions[key];
|
|
445
|
+
const actionConfig = moduleConfig.actions[actionName];
|
|
537
446
|
if (actionConfig.cacheResponse !== false) {
|
|
538
447
|
let currentQueryOptions;
|
|
539
|
-
if (isActionWithQuery(
|
|
540
|
-
currentQueryOptions = queries[
|
|
448
|
+
if (isActionWithQuery(actionName, moduleConfig.actions)) {
|
|
449
|
+
currentQueryOptions = queries[actionName]?.options;
|
|
541
450
|
}
|
|
542
451
|
const input = currentQueryOptions;
|
|
543
|
-
const pathParams =
|
|
544
|
-
const cacheKey = generateCacheKey(
|
|
545
|
-
|
|
452
|
+
const pathParams = JSON.parse(pathParamsString);
|
|
453
|
+
const cacheKey = generateCacheKey(
|
|
454
|
+
moduleConfig.baseEndpoint,
|
|
455
|
+
actionName,
|
|
456
|
+
input,
|
|
457
|
+
{ pathParams }
|
|
458
|
+
);
|
|
459
|
+
states[actionName] = useApiActionState(
|
|
460
|
+
actionConfig,
|
|
461
|
+
cacheKey,
|
|
462
|
+
actions[actionName].execute,
|
|
463
|
+
input,
|
|
464
|
+
enabled
|
|
465
|
+
);
|
|
546
466
|
} else {
|
|
547
467
|
states[actionName] = createInitialState();
|
|
548
468
|
}
|
|
@@ -553,10 +473,12 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
553
473
|
if (!enabled || !refetchOnWindowFocus) return;
|
|
554
474
|
const onFocus = () => {
|
|
555
475
|
if (Date.now() - lastBlurTimestamp.current > 1e4) {
|
|
556
|
-
|
|
476
|
+
const actionKeys = Object.keys(moduleConfig.actions);
|
|
477
|
+
for (const actionName of actionKeys) {
|
|
557
478
|
const state = states[actionName];
|
|
558
479
|
if (state && state.called && !state.loading) {
|
|
559
|
-
|
|
480
|
+
const prefix = `${moduleConfig.baseEndpoint}/${actionName}::`;
|
|
481
|
+
globalStateManager.invalidateByPrefix(prefix);
|
|
560
482
|
}
|
|
561
483
|
}
|
|
562
484
|
}
|
|
@@ -571,21 +493,19 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
571
493
|
window.removeEventListener("blur", onBlur);
|
|
572
494
|
};
|
|
573
495
|
}, [enabled, refetchOnWindowFocus, moduleConfig, states]);
|
|
574
|
-
const dehydrate =
|
|
496
|
+
const dehydrate = useMemo3(() => {
|
|
497
|
+
return () => globalStateManager.dehydrate();
|
|
498
|
+
}, []);
|
|
499
|
+
const baseApiReturn = { actions, states, queries, dehydrate };
|
|
575
500
|
const finalApiReturn = useMemo3(() => ({
|
|
576
|
-
|
|
577
|
-
states,
|
|
578
|
-
queries,
|
|
579
|
-
dehydrate,
|
|
501
|
+
...baseApiReturn,
|
|
580
502
|
...extraContextData || {}
|
|
581
|
-
|
|
582
|
-
// `actions` is stable and doesn't need to be a dependency.
|
|
583
|
-
}), [actions, states, queries, dehydrate, extraContextData]);
|
|
503
|
+
}), [baseApiReturn, extraContextData]);
|
|
584
504
|
return finalApiReturn;
|
|
585
505
|
}
|
|
586
506
|
|
|
587
507
|
// src/hooks/useApiModule/apiModuleContext.ts
|
|
588
|
-
import { createContext as createContext2, useContext, createElement } from "react";
|
|
508
|
+
import { createContext as createContext2, useContext as useContext2, createElement } from "react";
|
|
589
509
|
function createApiModuleContext() {
|
|
590
510
|
const Context = createContext2(null);
|
|
591
511
|
Context.displayName = "ApiModuleContext";
|
|
@@ -593,7 +513,7 @@ function createApiModuleContext() {
|
|
|
593
513
|
return createElement(Context.Provider, { value }, children);
|
|
594
514
|
};
|
|
595
515
|
const useConsumer = () => {
|
|
596
|
-
const context =
|
|
516
|
+
const context = useContext2(Context);
|
|
597
517
|
if (!context) {
|
|
598
518
|
throw new Error("This component must be used within its corresponding ApiModuleProvider.");
|
|
599
519
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AxiosInstance, AxiosRequestConfig, Method, AxiosResponse, AxiosError } from 'axios';
|
|
2
|
-
import {
|
|
3
|
-
export { o as ActionConfig,
|
|
4
|
-
export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-
|
|
2
|
+
import { f as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, g as ActionOptions, R as RequestConfig, h as ActionStateModule, Q as QueryOptions, i as UseApiQuery, j as ApiError, L as LogLevel } from './apiModule.types-hGWAkTwf.cjs';
|
|
3
|
+
export { o as ActionConfig, u as ActionMethods, q as ActionState, s as ActionsWithQuery, a as ApiModuleConfig, E as ExecutableAction, r as ExecuteOptions, I as InputOf, m as Middleware, l as MiddlewareContext, d as ModuleActions, e as ModuleQueries, M as ModuleStates, O as OutputOf, P as PaginationMeta, n as RefreshTokenConfig, k as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, p as UseApiState, V as ValidationError, t } from './apiModule.types-hGWAkTwf.cjs';
|
|
4
|
+
export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-V-4fiB7L.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 {
|
|
3
|
-
export { o as ActionConfig,
|
|
4
|
-
export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-
|
|
2
|
+
import { f as ApiClientConfig, A as ActionConfigModule, S as StandardResponse, g as ActionOptions, R as RequestConfig, h as ActionStateModule, Q as QueryOptions, i as UseApiQuery, j as ApiError, L as LogLevel } from './apiModule.types-hGWAkTwf.js';
|
|
3
|
+
export { o as ActionConfig, u as ActionMethods, q as ActionState, s as ActionsWithQuery, a as ApiModuleConfig, E as ExecutableAction, r as ExecuteOptions, I as InputOf, m as Middleware, l as MiddlewareContext, d as ModuleActions, e as ModuleQueries, M as ModuleStates, O as OutputOf, P as PaginationMeta, n as RefreshTokenConfig, k as TokenManager, T as Tokens, U as UseApiConfig, b as UseApiModuleOptions, c as UseApiModuleReturn, p as UseApiState, V as ValidationError, t } from './apiModule.types-hGWAkTwf.js';
|
|
4
|
+
export { c as UseApiRecordActions, U as UseApiRecordConfig, a as UseApiRecordReturn, b as UseApiRecordState } from './useApiRecord.types-BJop2XPB.js';
|
|
5
5
|
import 'react';
|
|
6
6
|
|
|
7
7
|
declare function createApiClient(config: ApiClientConfig): AxiosInstance;
|
package/dist/server.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosInstance } from 'axios';
|
|
2
|
-
import {
|
|
2
|
+
import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-hGWAkTwf.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 {
|
|
2
|
+
import { A as ActionConfigModule, a as ApiModuleConfig, I as InputOf } from './apiModule.types-hGWAkTwf.js';
|
|
3
3
|
import 'react';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from 'react';
|
|
2
|
-
import { R as RequestConfig, j as ApiError, S as StandardResponse, g as ActionOptions } from './apiModule.types-
|
|
2
|
+
import { R as RequestConfig, j as ApiError, S as StandardResponse, g as ActionOptions } from './apiModule.types-hGWAkTwf.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, j as ApiError, S as StandardResponse, g as ActionOptions } from './apiModule.types-
|
|
2
|
+
import { R as RequestConfig, j as ApiError, S as StandardResponse, g as ActionOptions } from './apiModule.types-hGWAkTwf.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Represents the internal state of the `useApiRecord` hook.
|