api-core-lib 16.12.135 → 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 +54 -159
- package/dist/client.d.cts +3 -3
- package/dist/client.d.ts +3 -3
- package/dist/client.js +46 -151
- 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,124 +321,29 @@ 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 pathParamsString = _react.useMemo.call(void 0, () => JSON.stringify(
|
|
334
|
-
const [queryOptions, setQueryOptions] = _react.useState.call(void 0,
|
|
335
|
-
const initialOptions = {};
|
|
336
|
-
for (const actionName in moduleConfig.actions) {
|
|
337
|
-
const actionConfig = moduleConfig.actions[actionName];
|
|
338
|
-
if (actionConfig._input) {
|
|
339
|
-
initialOptions[actionName] = { ...actionConfig._input };
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
if (defaultQueryOptions) {
|
|
343
|
-
for (const actionName in defaultQueryOptions) {
|
|
344
|
-
initialOptions[actionName] = {
|
|
345
|
-
...initialOptions[actionName],
|
|
346
|
-
...defaultQueryOptions[actionName]
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return initialOptions;
|
|
351
|
-
});
|
|
352
|
-
const lastCallRef = _react.useRef.call(void 0, {});
|
|
353
|
-
const initialFetchRef = _react.useRef.call(void 0, false);
|
|
354
|
-
const stableActionsRef = _react.useRef.call(void 0, {});
|
|
355
|
-
const isSyncingFromUrlRef = _react.useRef.call(void 0, false);
|
|
329
|
+
const pathParamsString = _react.useMemo.call(void 0, () => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
330
|
+
const [queryOptions, setQueryOptions] = _react.useState.call(void 0, {});
|
|
356
331
|
const savedCallbacks = _react.useRef.call(void 0, { onSuccess, onError });
|
|
357
332
|
_react.useEffect.call(void 0, () => {
|
|
358
333
|
savedCallbacks.current = { onSuccess, onError };
|
|
359
334
|
}, [onSuccess, onError]);
|
|
360
|
-
_react.
|
|
335
|
+
_react.useMemo.call(void 0, () => {
|
|
361
336
|
if (hydratedState) {
|
|
362
337
|
_chunkJAMEOM7Tcjs.globalStateManager.rehydrate(hydratedState);
|
|
363
338
|
}
|
|
364
339
|
}, [hydratedState]);
|
|
365
|
-
_react.
|
|
366
|
-
|
|
367
|
-
const { searchParams, actionsToSync, defaultSyncAction } = urlSync;
|
|
368
|
-
const params = new URLSearchParams(searchParams);
|
|
369
|
-
const queryFromUrl = {};
|
|
370
|
-
params.forEach((value, key) => {
|
|
371
|
-
const parts = key.split(".");
|
|
372
|
-
const hasPrefix = parts.length > 1;
|
|
373
|
-
const actionName = hasPrefix ? parts[0] : defaultSyncAction;
|
|
374
|
-
const paramKey = hasPrefix ? parts[1] : parts[0];
|
|
375
|
-
if (actionName && paramKey && actionsToSync.some((a) => a === actionName)) {
|
|
376
|
-
if (!queryFromUrl[actionName]) queryFromUrl[actionName] = {};
|
|
377
|
-
const isNum = !isNaN(Number(value)) && value.trim() !== "";
|
|
378
|
-
queryFromUrl[actionName][paramKey] = isNum ? Number(value) : value;
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
if (Object.keys(queryFromUrl).length > 0) {
|
|
382
|
-
isSyncingFromUrlRef.current = true;
|
|
383
|
-
setQueryOptions((prev) => {
|
|
384
|
-
const newState = { ...prev };
|
|
385
|
-
let hasChanged = false;
|
|
386
|
-
for (const actionName in queryFromUrl) {
|
|
387
|
-
const newOpts = { ...newState[actionName], ...queryFromUrl[actionName] };
|
|
388
|
-
if (JSON.stringify(newState[actionName]) !== JSON.stringify(newOpts)) {
|
|
389
|
-
newState[actionName] = newOpts;
|
|
390
|
-
hasChanged = true;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return hasChanged ? newState : prev;
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
}, [_optionalChain([urlSync, 'optionalAccess', _6 => _6.searchParams]), _optionalChain([urlSync, 'optionalAccess', _7 => _7.actionsToSync]), _optionalChain([urlSync, 'optionalAccess', _8 => _8.defaultSyncAction])]);
|
|
397
|
-
_react.useEffect.call(void 0, () => {
|
|
398
|
-
if (!urlSync) return;
|
|
399
|
-
if (isSyncingFromUrlRef.current) {
|
|
400
|
-
isSyncingFromUrlRef.current = false;
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
const { searchParams, updateUrl, actionsToSync, defaultSyncAction } = urlSync;
|
|
404
|
-
const currentParams = new URLSearchParams(searchParams);
|
|
405
|
-
let hasChanged = false;
|
|
406
|
-
const newParams = new URLSearchParams();
|
|
407
|
-
for (const actionName in queryOptions) {
|
|
408
|
-
if (actionsToSync.some((a) => a === actionName)) {
|
|
409
|
-
const params = queryOptions[actionName];
|
|
410
|
-
const isDefaultAction = actionName === defaultSyncAction;
|
|
411
|
-
for (const key in params) {
|
|
412
|
-
const fullKey = isDefaultAction ? key : `${actionName}.${key}`;
|
|
413
|
-
const value = params[key];
|
|
414
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
415
|
-
newParams.set(fullKey, String(value));
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (newParams.toString() !== currentParams.toString()) {
|
|
421
|
-
updateUrl(newParams.toString());
|
|
422
|
-
}
|
|
423
|
-
}, [queryOptions, _optionalChain([urlSync, 'optionalAccess', _9 => _9.updateUrl]), _optionalChain([urlSync, 'optionalAccess', _10 => _10.actionsToSync]), _optionalChain([urlSync, 'optionalAccess', _11 => _11.defaultSyncAction])]);
|
|
424
|
-
_react.useMemo.call(void 0, () => {
|
|
425
|
-
for (const actionName in moduleConfig.actions) {
|
|
340
|
+
const actions = _react.useMemo.call(void 0, () => {
|
|
341
|
+
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
426
342
|
const actionConfig = moduleConfig.actions[actionName];
|
|
427
343
|
const shouldCache = actionConfig.cacheResponse !== false;
|
|
428
344
|
const execute = async (input, options2 = {}) => {
|
|
429
|
-
lastCallRef.current[actionName] = { input, options: options2 };
|
|
430
345
|
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
431
|
-
|
|
432
|
-
let requestConfig = options2.config || {};
|
|
433
|
-
if (actionConfig.method === "GET") {
|
|
434
|
-
const currentQueryOptions = queryOptions[actionName];
|
|
435
|
-
bodyForCall = { ...actionConfig._input, ...currentQueryOptions, ..._optionalChain([options2, 'access', _12 => _12.config, 'optionalAccess', _13 => _13.params]), ...input };
|
|
436
|
-
} else if (actionConfig.upload && input) {
|
|
437
|
-
bodyForCall = new FormData();
|
|
438
|
-
for (const key in input) {
|
|
439
|
-
bodyForCall.append(key, input[key]);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
const cacheKey = shouldCache ? _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0, moduleConfig.baseEndpoint, actionName, bodyForCall, { pathParams: finalPathParams }) : "";
|
|
346
|
+
const cacheKey = shouldCache ? _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0, moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
|
|
443
347
|
let mutationContext;
|
|
444
348
|
try {
|
|
445
349
|
if (options2.onMutate && shouldCache) {
|
|
@@ -450,8 +354,8 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
450
354
|
}
|
|
451
355
|
const result = await _chunkJAMEOM7Tcjs.callDynamicApi.call(void 0, axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
|
|
452
356
|
pathParams: finalPathParams,
|
|
453
|
-
body:
|
|
454
|
-
config:
|
|
357
|
+
body: input,
|
|
358
|
+
config: options2.config
|
|
455
359
|
});
|
|
456
360
|
if (shouldCache) {
|
|
457
361
|
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, (prev) => ({
|
|
@@ -464,29 +368,28 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
464
368
|
links: result.links,
|
|
465
369
|
message: result.message,
|
|
466
370
|
validationErrors: result.validationErrors || [],
|
|
467
|
-
rawResponse: result.rawResponse
|
|
468
|
-
lastSuccessAt: result.success ? Date.now() : prev.lastSuccessAt
|
|
371
|
+
rawResponse: result.rawResponse
|
|
469
372
|
}));
|
|
470
373
|
}
|
|
471
374
|
if (result.success) {
|
|
472
|
-
_optionalChain([savedCallbacks, 'access',
|
|
473
|
-
_optionalChain([options2, 'access',
|
|
474
|
-
_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) => {
|
|
475
378
|
const prefix = `${moduleConfig.baseEndpoint}/${keyToInvalidate}::`;
|
|
476
379
|
_chunkJAMEOM7Tcjs.globalStateManager.invalidateByPrefix(prefix);
|
|
477
380
|
})]);
|
|
478
381
|
} else {
|
|
479
|
-
_optionalChain([savedCallbacks, 'access',
|
|
480
|
-
_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)]);
|
|
481
384
|
}
|
|
482
385
|
return result;
|
|
483
386
|
} catch (error) {
|
|
484
|
-
const apiError = _optionalChain([error, 'access',
|
|
387
|
+
const apiError = _optionalChain([error, 'access', _19 => _19.response, 'optionalAccess', _20 => _20.data]) || { status: 500, message: error.message };
|
|
485
388
|
if (shouldCache) {
|
|
486
389
|
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, (prev) => ({ ...prev, error: apiError, loading: false, success: false }));
|
|
487
390
|
}
|
|
488
|
-
_optionalChain([savedCallbacks, 'access',
|
|
489
|
-
_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)]);
|
|
490
393
|
throw error;
|
|
491
394
|
} finally {
|
|
492
395
|
if (options2.onSettled) {
|
|
@@ -501,41 +404,21 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
501
404
|
_chunkJAMEOM7Tcjs.globalStateManager.setState(cacheKey, () => createInitialState());
|
|
502
405
|
}
|
|
503
406
|
};
|
|
504
|
-
|
|
505
|
-
|
|
407
|
+
acc[actionName] = { execute, reset };
|
|
408
|
+
return acc;
|
|
409
|
+
}, {});
|
|
506
410
|
}, [axiosInstance, moduleConfig, pathParamsString]);
|
|
507
|
-
const actions = _react.useMemo.call(void 0, () => stableActionsRef.current, []);
|
|
508
|
-
_react.useEffect.call(void 0, () => {
|
|
509
|
-
if (typeof window === "undefined" || initialFetchRef.current || !enabled) return;
|
|
510
|
-
const actionsToRun = initialActionsToExecute ? initialActionsToExecute.map(String) : Object.keys(moduleConfig.actions).filter(
|
|
511
|
-
(actionName) => moduleConfig.actions[actionName].autoFetch
|
|
512
|
-
);
|
|
513
|
-
actionsToRun.forEach((actionName) => {
|
|
514
|
-
const key = actionName;
|
|
515
|
-
const hydratedData = hydratedState ? JSON.parse(hydratedState) : {};
|
|
516
|
-
if (_optionalChain([hydratedData, 'access', _34 => _34[actionName], 'optionalAccess', _35 => _35.data])) {
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
const actionConfig = moduleConfig.actions[key];
|
|
520
|
-
const executeAction = _optionalChain([actions, 'access', _36 => _36[key], 'optionalAccess', _37 => _37.execute]);
|
|
521
|
-
if (typeof executeAction === "function") {
|
|
522
|
-
const input = actionConfig.hasQuery ? queryOptions[actionName] : void 0;
|
|
523
|
-
executeAction(input);
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
initialFetchRef.current = true;
|
|
527
|
-
}, [actions, initialActionsToExecute, moduleConfig.actions, hydratedState, queryOptions, enabled]);
|
|
528
411
|
const queries = _react.useMemo.call(void 0, () => {
|
|
529
412
|
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
530
413
|
const actionConfig = moduleConfig.actions[actionName];
|
|
531
|
-
if (_optionalChain([actionConfig, 'optionalAccess',
|
|
414
|
+
if (_optionalChain([actionConfig, 'optionalAccess', _26 => _26.hasQuery])) {
|
|
532
415
|
const setActionQueryOptions = (updater) => {
|
|
533
416
|
const key = actionName;
|
|
534
417
|
setQueryOptions((prev) => ({ ...prev, [key]: typeof updater === "function" ? updater(prev[key] || {}) : updater }));
|
|
535
418
|
};
|
|
419
|
+
const specificActionExecute = actions[actionName].execute;
|
|
536
420
|
const refetch = () => {
|
|
537
|
-
|
|
538
|
-
execute(queryOptions[actionName] || {});
|
|
421
|
+
specificActionExecute(queryOptions[actionName] || {});
|
|
539
422
|
};
|
|
540
423
|
acc[actionName] = {
|
|
541
424
|
options: queryOptions[actionName] || {},
|
|
@@ -547,7 +430,7 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
547
430
|
setFilters: (filter) => setActionQueryOptions((p) => ({ ...p, filter, page: 1 })),
|
|
548
431
|
setSorting: (sortBy) => setActionQueryOptions((p) => ({ ...p, sortBy })),
|
|
549
432
|
setQueryParam: (key, value) => setActionQueryOptions((p) => ({ ...p, [key]: value, page: key !== "page" ? value : p.page })),
|
|
550
|
-
reset: () => setActionQueryOptions(
|
|
433
|
+
reset: () => setActionQueryOptions({})
|
|
551
434
|
};
|
|
552
435
|
}
|
|
553
436
|
return acc;
|
|
@@ -555,21 +438,31 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
555
438
|
}, [actions, queryOptions, moduleConfig.actions]);
|
|
556
439
|
const states = {};
|
|
557
440
|
function isActionWithQuery(key, actions2) {
|
|
558
|
-
return _optionalChain([actions2, 'access',
|
|
441
|
+
return _optionalChain([actions2, 'access', _27 => _27[key], 'optionalAccess', _28 => _28.hasQuery]) === true;
|
|
559
442
|
}
|
|
560
443
|
for (const actionName in moduleConfig.actions) {
|
|
561
444
|
if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
|
|
562
|
-
const
|
|
563
|
-
const actionConfig = moduleConfig.actions[key];
|
|
445
|
+
const actionConfig = moduleConfig.actions[actionName];
|
|
564
446
|
if (actionConfig.cacheResponse !== false) {
|
|
565
447
|
let currentQueryOptions;
|
|
566
|
-
if (isActionWithQuery(
|
|
567
|
-
currentQueryOptions = _optionalChain([queries, 'access',
|
|
448
|
+
if (isActionWithQuery(actionName, moduleConfig.actions)) {
|
|
449
|
+
currentQueryOptions = _optionalChain([queries, 'access', _29 => _29[actionName], 'optionalAccess', _30 => _30.options]);
|
|
568
450
|
}
|
|
569
451
|
const input = currentQueryOptions;
|
|
570
452
|
const pathParams = JSON.parse(pathParamsString);
|
|
571
|
-
const cacheKey = _chunkJAMEOM7Tcjs.generateCacheKey.call(void 0,
|
|
572
|
-
|
|
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
|
+
);
|
|
573
466
|
} else {
|
|
574
467
|
states[actionName] = createInitialState();
|
|
575
468
|
}
|
|
@@ -580,10 +473,12 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
580
473
|
if (!enabled || !refetchOnWindowFocus) return;
|
|
581
474
|
const onFocus = () => {
|
|
582
475
|
if (Date.now() - lastBlurTimestamp.current > 1e4) {
|
|
583
|
-
|
|
476
|
+
const actionKeys = Object.keys(moduleConfig.actions);
|
|
477
|
+
for (const actionName of actionKeys) {
|
|
584
478
|
const state = states[actionName];
|
|
585
479
|
if (state && state.called && !state.loading) {
|
|
586
|
-
|
|
480
|
+
const prefix = `${moduleConfig.baseEndpoint}/${actionName}::`;
|
|
481
|
+
_chunkJAMEOM7Tcjs.globalStateManager.invalidateByPrefix(prefix);
|
|
587
482
|
}
|
|
588
483
|
}
|
|
589
484
|
}
|
|
@@ -598,14 +493,14 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
598
493
|
window.removeEventListener("blur", onBlur);
|
|
599
494
|
};
|
|
600
495
|
}, [enabled, refetchOnWindowFocus, moduleConfig, states]);
|
|
601
|
-
const dehydrate = _react.
|
|
496
|
+
const dehydrate = _react.useMemo.call(void 0, () => {
|
|
497
|
+
return () => _chunkJAMEOM7Tcjs.globalStateManager.dehydrate();
|
|
498
|
+
}, []);
|
|
499
|
+
const baseApiReturn = { actions, states, queries, dehydrate };
|
|
602
500
|
const finalApiReturn = _react.useMemo.call(void 0, () => ({
|
|
603
|
-
|
|
604
|
-
states,
|
|
605
|
-
queries,
|
|
606
|
-
dehydrate,
|
|
501
|
+
...baseApiReturn,
|
|
607
502
|
...extraContextData || {}
|
|
608
|
-
}), [
|
|
503
|
+
}), [baseApiReturn, extraContextData]);
|
|
609
504
|
return finalApiReturn;
|
|
610
505
|
}
|
|
611
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,124 +321,29 @@ 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 pathParamsString = useMemo3(() => JSON.stringify(
|
|
334
|
-
const [queryOptions, setQueryOptions] = useState3(
|
|
335
|
-
const initialOptions = {};
|
|
336
|
-
for (const actionName in moduleConfig.actions) {
|
|
337
|
-
const actionConfig = moduleConfig.actions[actionName];
|
|
338
|
-
if (actionConfig._input) {
|
|
339
|
-
initialOptions[actionName] = { ...actionConfig._input };
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
if (defaultQueryOptions) {
|
|
343
|
-
for (const actionName in defaultQueryOptions) {
|
|
344
|
-
initialOptions[actionName] = {
|
|
345
|
-
...initialOptions[actionName],
|
|
346
|
-
...defaultQueryOptions[actionName]
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return initialOptions;
|
|
351
|
-
});
|
|
352
|
-
const lastCallRef = useRef4({});
|
|
353
|
-
const initialFetchRef = useRef4(false);
|
|
354
|
-
const stableActionsRef = useRef4({});
|
|
355
|
-
const isSyncingFromUrlRef = useRef4(false);
|
|
329
|
+
const pathParamsString = useMemo3(() => JSON.stringify(modulePathParams || {}), [modulePathParams]);
|
|
330
|
+
const [queryOptions, setQueryOptions] = useState3({});
|
|
356
331
|
const savedCallbacks = useRef4({ onSuccess, onError });
|
|
357
332
|
useEffect4(() => {
|
|
358
333
|
savedCallbacks.current = { onSuccess, onError };
|
|
359
334
|
}, [onSuccess, onError]);
|
|
360
|
-
|
|
335
|
+
useMemo3(() => {
|
|
361
336
|
if (hydratedState) {
|
|
362
337
|
globalStateManager.rehydrate(hydratedState);
|
|
363
338
|
}
|
|
364
339
|
}, [hydratedState]);
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const { searchParams, actionsToSync, defaultSyncAction } = urlSync;
|
|
368
|
-
const params = new URLSearchParams(searchParams);
|
|
369
|
-
const queryFromUrl = {};
|
|
370
|
-
params.forEach((value, key) => {
|
|
371
|
-
const parts = key.split(".");
|
|
372
|
-
const hasPrefix = parts.length > 1;
|
|
373
|
-
const actionName = hasPrefix ? parts[0] : defaultSyncAction;
|
|
374
|
-
const paramKey = hasPrefix ? parts[1] : parts[0];
|
|
375
|
-
if (actionName && paramKey && actionsToSync.some((a) => a === actionName)) {
|
|
376
|
-
if (!queryFromUrl[actionName]) queryFromUrl[actionName] = {};
|
|
377
|
-
const isNum = !isNaN(Number(value)) && value.trim() !== "";
|
|
378
|
-
queryFromUrl[actionName][paramKey] = isNum ? Number(value) : value;
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
if (Object.keys(queryFromUrl).length > 0) {
|
|
382
|
-
isSyncingFromUrlRef.current = true;
|
|
383
|
-
setQueryOptions((prev) => {
|
|
384
|
-
const newState = { ...prev };
|
|
385
|
-
let hasChanged = false;
|
|
386
|
-
for (const actionName in queryFromUrl) {
|
|
387
|
-
const newOpts = { ...newState[actionName], ...queryFromUrl[actionName] };
|
|
388
|
-
if (JSON.stringify(newState[actionName]) !== JSON.stringify(newOpts)) {
|
|
389
|
-
newState[actionName] = newOpts;
|
|
390
|
-
hasChanged = true;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return hasChanged ? newState : prev;
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
}, [urlSync?.searchParams, urlSync?.actionsToSync, urlSync?.defaultSyncAction]);
|
|
397
|
-
useEffect4(() => {
|
|
398
|
-
if (!urlSync) return;
|
|
399
|
-
if (isSyncingFromUrlRef.current) {
|
|
400
|
-
isSyncingFromUrlRef.current = false;
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
const { searchParams, updateUrl, actionsToSync, defaultSyncAction } = urlSync;
|
|
404
|
-
const currentParams = new URLSearchParams(searchParams);
|
|
405
|
-
let hasChanged = false;
|
|
406
|
-
const newParams = new URLSearchParams();
|
|
407
|
-
for (const actionName in queryOptions) {
|
|
408
|
-
if (actionsToSync.some((a) => a === actionName)) {
|
|
409
|
-
const params = queryOptions[actionName];
|
|
410
|
-
const isDefaultAction = actionName === defaultSyncAction;
|
|
411
|
-
for (const key in params) {
|
|
412
|
-
const fullKey = isDefaultAction ? key : `${actionName}.${key}`;
|
|
413
|
-
const value = params[key];
|
|
414
|
-
if (value !== void 0 && value !== null && value !== "") {
|
|
415
|
-
newParams.set(fullKey, String(value));
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
if (newParams.toString() !== currentParams.toString()) {
|
|
421
|
-
updateUrl(newParams.toString());
|
|
422
|
-
}
|
|
423
|
-
}, [queryOptions, urlSync?.updateUrl, urlSync?.actionsToSync, urlSync?.defaultSyncAction]);
|
|
424
|
-
useMemo3(() => {
|
|
425
|
-
for (const actionName in moduleConfig.actions) {
|
|
340
|
+
const actions = useMemo3(() => {
|
|
341
|
+
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
426
342
|
const actionConfig = moduleConfig.actions[actionName];
|
|
427
343
|
const shouldCache = actionConfig.cacheResponse !== false;
|
|
428
344
|
const execute = async (input, options2 = {}) => {
|
|
429
|
-
lastCallRef.current[actionName] = { input, options: options2 };
|
|
430
345
|
const finalPathParams = { ...JSON.parse(pathParamsString), ...options2.pathParams };
|
|
431
|
-
|
|
432
|
-
let requestConfig = options2.config || {};
|
|
433
|
-
if (actionConfig.method === "GET") {
|
|
434
|
-
const currentQueryOptions = queryOptions[actionName];
|
|
435
|
-
bodyForCall = { ...actionConfig._input, ...currentQueryOptions, ...options2.config?.params, ...input };
|
|
436
|
-
} else if (actionConfig.upload && input) {
|
|
437
|
-
bodyForCall = new FormData();
|
|
438
|
-
for (const key in input) {
|
|
439
|
-
bodyForCall.append(key, input[key]);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, bodyForCall, { pathParams: finalPathParams }) : "";
|
|
346
|
+
const cacheKey = shouldCache ? generateCacheKey(moduleConfig.baseEndpoint, actionName, input, { pathParams: finalPathParams }) : "";
|
|
443
347
|
let mutationContext;
|
|
444
348
|
try {
|
|
445
349
|
if (options2.onMutate && shouldCache) {
|
|
@@ -450,8 +354,8 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
450
354
|
}
|
|
451
355
|
const result = await callDynamicApi(axiosInstance, moduleConfig.baseEndpoint, actionConfig, {
|
|
452
356
|
pathParams: finalPathParams,
|
|
453
|
-
body:
|
|
454
|
-
config:
|
|
357
|
+
body: input,
|
|
358
|
+
config: options2.config
|
|
455
359
|
});
|
|
456
360
|
if (shouldCache) {
|
|
457
361
|
globalStateManager.setState(cacheKey, (prev) => ({
|
|
@@ -464,8 +368,7 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
464
368
|
links: result.links,
|
|
465
369
|
message: result.message,
|
|
466
370
|
validationErrors: result.validationErrors || [],
|
|
467
|
-
rawResponse: result.rawResponse
|
|
468
|
-
lastSuccessAt: result.success ? Date.now() : prev.lastSuccessAt
|
|
371
|
+
rawResponse: result.rawResponse
|
|
469
372
|
}));
|
|
470
373
|
}
|
|
471
374
|
if (result.success) {
|
|
@@ -501,30 +404,10 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
501
404
|
globalStateManager.setState(cacheKey, () => createInitialState());
|
|
502
405
|
}
|
|
503
406
|
};
|
|
504
|
-
|
|
505
|
-
|
|
407
|
+
acc[actionName] = { execute, reset };
|
|
408
|
+
return acc;
|
|
409
|
+
}, {});
|
|
506
410
|
}, [axiosInstance, moduleConfig, pathParamsString]);
|
|
507
|
-
const actions = useMemo3(() => stableActionsRef.current, []);
|
|
508
|
-
useEffect4(() => {
|
|
509
|
-
if (typeof window === "undefined" || initialFetchRef.current || !enabled) return;
|
|
510
|
-
const actionsToRun = initialActionsToExecute ? initialActionsToExecute.map(String) : Object.keys(moduleConfig.actions).filter(
|
|
511
|
-
(actionName) => moduleConfig.actions[actionName].autoFetch
|
|
512
|
-
);
|
|
513
|
-
actionsToRun.forEach((actionName) => {
|
|
514
|
-
const key = actionName;
|
|
515
|
-
const hydratedData = hydratedState ? JSON.parse(hydratedState) : {};
|
|
516
|
-
if (hydratedData[actionName]?.data) {
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
const actionConfig = moduleConfig.actions[key];
|
|
520
|
-
const executeAction = actions[key]?.execute;
|
|
521
|
-
if (typeof executeAction === "function") {
|
|
522
|
-
const input = actionConfig.hasQuery ? queryOptions[actionName] : void 0;
|
|
523
|
-
executeAction(input);
|
|
524
|
-
}
|
|
525
|
-
});
|
|
526
|
-
initialFetchRef.current = true;
|
|
527
|
-
}, [actions, initialActionsToExecute, moduleConfig.actions, hydratedState, queryOptions, enabled]);
|
|
528
411
|
const queries = useMemo3(() => {
|
|
529
412
|
return Object.keys(moduleConfig.actions).reduce((acc, actionName) => {
|
|
530
413
|
const actionConfig = moduleConfig.actions[actionName];
|
|
@@ -533,9 +416,9 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
533
416
|
const key = actionName;
|
|
534
417
|
setQueryOptions((prev) => ({ ...prev, [key]: typeof updater === "function" ? updater(prev[key] || {}) : updater }));
|
|
535
418
|
};
|
|
419
|
+
const specificActionExecute = actions[actionName].execute;
|
|
536
420
|
const refetch = () => {
|
|
537
|
-
|
|
538
|
-
execute(queryOptions[actionName] || {});
|
|
421
|
+
specificActionExecute(queryOptions[actionName] || {});
|
|
539
422
|
};
|
|
540
423
|
acc[actionName] = {
|
|
541
424
|
options: queryOptions[actionName] || {},
|
|
@@ -547,7 +430,7 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
547
430
|
setFilters: (filter) => setActionQueryOptions((p) => ({ ...p, filter, page: 1 })),
|
|
548
431
|
setSorting: (sortBy) => setActionQueryOptions((p) => ({ ...p, sortBy })),
|
|
549
432
|
setQueryParam: (key, value) => setActionQueryOptions((p) => ({ ...p, [key]: value, page: key !== "page" ? value : p.page })),
|
|
550
|
-
reset: () => setActionQueryOptions(
|
|
433
|
+
reset: () => setActionQueryOptions({})
|
|
551
434
|
};
|
|
552
435
|
}
|
|
553
436
|
return acc;
|
|
@@ -559,17 +442,27 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
559
442
|
}
|
|
560
443
|
for (const actionName in moduleConfig.actions) {
|
|
561
444
|
if (Object.prototype.hasOwnProperty.call(moduleConfig.actions, actionName)) {
|
|
562
|
-
const
|
|
563
|
-
const actionConfig = moduleConfig.actions[key];
|
|
445
|
+
const actionConfig = moduleConfig.actions[actionName];
|
|
564
446
|
if (actionConfig.cacheResponse !== false) {
|
|
565
447
|
let currentQueryOptions;
|
|
566
|
-
if (isActionWithQuery(
|
|
567
|
-
currentQueryOptions = queries[
|
|
448
|
+
if (isActionWithQuery(actionName, moduleConfig.actions)) {
|
|
449
|
+
currentQueryOptions = queries[actionName]?.options;
|
|
568
450
|
}
|
|
569
451
|
const input = currentQueryOptions;
|
|
570
452
|
const pathParams = JSON.parse(pathParamsString);
|
|
571
|
-
const cacheKey = generateCacheKey(
|
|
572
|
-
|
|
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
|
+
);
|
|
573
466
|
} else {
|
|
574
467
|
states[actionName] = createInitialState();
|
|
575
468
|
}
|
|
@@ -580,10 +473,12 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
580
473
|
if (!enabled || !refetchOnWindowFocus) return;
|
|
581
474
|
const onFocus = () => {
|
|
582
475
|
if (Date.now() - lastBlurTimestamp.current > 1e4) {
|
|
583
|
-
|
|
476
|
+
const actionKeys = Object.keys(moduleConfig.actions);
|
|
477
|
+
for (const actionName of actionKeys) {
|
|
584
478
|
const state = states[actionName];
|
|
585
479
|
if (state && state.called && !state.loading) {
|
|
586
|
-
|
|
480
|
+
const prefix = `${moduleConfig.baseEndpoint}/${actionName}::`;
|
|
481
|
+
globalStateManager.invalidateByPrefix(prefix);
|
|
587
482
|
}
|
|
588
483
|
}
|
|
589
484
|
}
|
|
@@ -598,19 +493,19 @@ function useApiModule(axiosInstance, moduleConfig, options = {}) {
|
|
|
598
493
|
window.removeEventListener("blur", onBlur);
|
|
599
494
|
};
|
|
600
495
|
}, [enabled, refetchOnWindowFocus, moduleConfig, states]);
|
|
601
|
-
const dehydrate =
|
|
496
|
+
const dehydrate = useMemo3(() => {
|
|
497
|
+
return () => globalStateManager.dehydrate();
|
|
498
|
+
}, []);
|
|
499
|
+
const baseApiReturn = { actions, states, queries, dehydrate };
|
|
602
500
|
const finalApiReturn = useMemo3(() => ({
|
|
603
|
-
|
|
604
|
-
states,
|
|
605
|
-
queries,
|
|
606
|
-
dehydrate,
|
|
501
|
+
...baseApiReturn,
|
|
607
502
|
...extraContextData || {}
|
|
608
|
-
}), [
|
|
503
|
+
}), [baseApiReturn, extraContextData]);
|
|
609
504
|
return finalApiReturn;
|
|
610
505
|
}
|
|
611
506
|
|
|
612
507
|
// src/hooks/useApiModule/apiModuleContext.ts
|
|
613
|
-
import { createContext as createContext2, useContext, createElement } from "react";
|
|
508
|
+
import { createContext as createContext2, useContext as useContext2, createElement } from "react";
|
|
614
509
|
function createApiModuleContext() {
|
|
615
510
|
const Context = createContext2(null);
|
|
616
511
|
Context.displayName = "ApiModuleContext";
|
|
@@ -618,7 +513,7 @@ function createApiModuleContext() {
|
|
|
618
513
|
return createElement(Context.Provider, { value }, children);
|
|
619
514
|
};
|
|
620
515
|
const useConsumer = () => {
|
|
621
|
-
const context =
|
|
516
|
+
const context = useContext2(Context);
|
|
622
517
|
if (!context) {
|
|
623
518
|
throw new Error("This component must be used within its corresponding ApiModuleProvider.");
|
|
624
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.
|