api-core-lib 4.4.4 → 5.5.4
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/index.d.mts +59 -21
- package/dist/index.d.ts +59 -21
- package/dist/index.js +66 -42
- package/dist/index.mjs +66 -42
- package/package.json +39 -39
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosProgressEvent, AxiosInstance, Method } from 'axios';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -35,28 +35,49 @@ interface ApiError {
|
|
|
35
35
|
errors?: ValidationError[];
|
|
36
36
|
requestId?: string;
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
39
|
-
* يمثل مجموعة التوكنات التي يتم إدارتها.
|
|
40
|
-
*/
|
|
41
38
|
interface Tokens {
|
|
42
39
|
accessToken: string | null;
|
|
43
40
|
refreshToken: string | null;
|
|
44
41
|
expiresAt?: number;
|
|
45
42
|
tokenType?: string;
|
|
46
43
|
}
|
|
47
|
-
/**
|
|
48
|
-
* واجهة لمدير التوكنات، تسمح بفصل منطق تخزين التوكن.
|
|
49
|
-
* يمكن للمستخدم توفير تطبيق لهذه الواجهة (e.g., LocalStorage, Cookies).
|
|
50
|
-
*/
|
|
51
44
|
interface TokenManager {
|
|
52
45
|
getTokens(): Promise<Tokens>;
|
|
53
46
|
setTokens(tokens: Tokens): Promise<void>;
|
|
54
47
|
clearTokens(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* دالة لتحديد سياق التشغيل.
|
|
50
|
+
* true إذا كانت التوكنات في كوكيز httpOnly (الوضع الآمن).
|
|
51
|
+
* false إذا كانت في مكان يمكن للعميل الوصول إليه (للتطبيقات غير Next.js).
|
|
52
|
+
*/
|
|
55
53
|
isHttpOnly(): boolean;
|
|
56
54
|
}
|
|
57
55
|
/**
|
|
58
|
-
*
|
|
56
|
+
* واجهة لـ Logger مخصص. متوافقة مع `console`.
|
|
59
57
|
*/
|
|
58
|
+
interface Logger {
|
|
59
|
+
log(message?: any, ...optionalParams: any[]): void;
|
|
60
|
+
info(message?: any, ...optionalParams: any[]): void;
|
|
61
|
+
warn(message?: any, ...optionalParams: any[]): void;
|
|
62
|
+
error(message?: any, ...optionalParams: any[]): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* سياق البرمجيات الوسيطة الذي يتم تمريره لكل دالة.
|
|
66
|
+
*/
|
|
67
|
+
interface MiddlewareContext {
|
|
68
|
+
req: InternalAxiosRequestConfig;
|
|
69
|
+
res?: AxiosResponse;
|
|
70
|
+
error?: any;
|
|
71
|
+
logger: Logger;
|
|
72
|
+
custom?: Record<string, any>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* دالة برمجية وسيطة (Middleware Function).
|
|
76
|
+
*/
|
|
77
|
+
type Middleware = (context: MiddlewareContext, next: () => Promise<void>) => Promise<void>;
|
|
78
|
+
interface RequestConfig extends AxiosRequestConfig {
|
|
79
|
+
isPublic?: boolean;
|
|
80
|
+
}
|
|
60
81
|
interface RequestConfig extends AxiosRequestConfig {
|
|
61
82
|
cancelTokenKey?: string;
|
|
62
83
|
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
|
@@ -113,7 +134,7 @@ interface RefreshTokenConfig {
|
|
|
113
134
|
};
|
|
114
135
|
}
|
|
115
136
|
/**
|
|
116
|
-
* الواجهة الرئيسية لتهيئة عميل الـ API.
|
|
137
|
+
* الواجهة الرئيسية لتهيئة عميل الـ API (محدثة بالكامل).
|
|
117
138
|
*/
|
|
118
139
|
interface ApiClientConfig {
|
|
119
140
|
baseURL?: string;
|
|
@@ -121,13 +142,16 @@ interface ApiClientConfig {
|
|
|
121
142
|
timeout?: number;
|
|
122
143
|
headers?: Record<string, string>;
|
|
123
144
|
withCredentials?: boolean;
|
|
124
|
-
responseType?: ResponseType;
|
|
125
|
-
/**
|
|
126
|
-
* إعدادات مخصصة لعملية تجديد التوكن.
|
|
127
|
-
* إذا لم يتم توفيرها، ستتوقف محاولات التجديد التلقائي.
|
|
128
|
-
*/
|
|
129
145
|
refreshTokenConfig?: RefreshTokenConfig;
|
|
130
146
|
onRefreshError?: (error: any) => void;
|
|
147
|
+
/**
|
|
148
|
+
* ✨ NEW: Logger مخصص. الافتراضي هو `console`.
|
|
149
|
+
*/
|
|
150
|
+
logger?: Logger;
|
|
151
|
+
/**
|
|
152
|
+
* ✨ NEW: مصفوفة من البرمجيات الوسيطة (Middleware) لتشغيلها مع كل طلب.
|
|
153
|
+
*/
|
|
154
|
+
middleware?: Middleware[];
|
|
131
155
|
}
|
|
132
156
|
/**
|
|
133
157
|
* يمثل بنية الاستجابة القياسية من الـ API.
|
|
@@ -214,12 +238,25 @@ interface UseApiConfig<T> {
|
|
|
214
238
|
|
|
215
239
|
/**
|
|
216
240
|
* @file src/core/client.ts
|
|
217
|
-
* @description
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
241
|
+
* @description This is the heart of the API client library.
|
|
242
|
+
* The `createApiClient` function constructs and configures a sophisticated Axios instance.
|
|
243
|
+
* It features intelligent, security-first token management, a flexible middleware system,
|
|
244
|
+
* and customizable logging, all designed to work seamlessly in modern web frameworks like Next.js.
|
|
221
245
|
*/
|
|
222
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Creates and configures a new Axios instance with advanced features.
|
|
249
|
+
*
|
|
250
|
+
* This factory function is the central entry point of the library. It sets up
|
|
251
|
+
* request and response interceptors to handle:
|
|
252
|
+
* - Secure token management (supporting httpOnly and client-side storage).
|
|
253
|
+
* - A flexible middleware pipeline for custom logic.
|
|
254
|
+
* - Centralized logging for observability.
|
|
255
|
+
* - Automatic token refresh for client-side scenarios.
|
|
256
|
+
*
|
|
257
|
+
* @param {ApiClientConfig} config - The configuration object for the API client.
|
|
258
|
+
* @returns {AxiosInstance} A fully configured Axios instance ready for use.
|
|
259
|
+
*/
|
|
223
260
|
declare function createApiClient(config: ApiClientConfig): AxiosInstance;
|
|
224
261
|
|
|
225
262
|
type CrudRequestConfig = RequestConfig & ActionOptions;
|
|
@@ -283,6 +320,7 @@ declare function createApiActions<TActions extends Record<string, {
|
|
|
283
320
|
endpoint: string;
|
|
284
321
|
requestType: any;
|
|
285
322
|
responseType: any;
|
|
323
|
+
log?: boolean;
|
|
286
324
|
}>>(axiosInstance: AxiosInstance, actionsConfig: TActions): {
|
|
287
325
|
[K in keyof TActions]: ApiAction<TActions[K]['requestType'], TActions[K]['responseType']>;
|
|
288
326
|
};
|
|
@@ -306,7 +344,7 @@ declare const cacheManager: CacheManager;
|
|
|
306
344
|
* @param responseOrError The raw Axios response or a pre-processed ApiError.
|
|
307
345
|
* @returns A standardized `StandardResponse` object with direct access to `.data`.
|
|
308
346
|
*/
|
|
309
|
-
declare const processResponse: <T>(responseOrError: AxiosResponse<any> | ApiError) => StandardResponse<T>;
|
|
347
|
+
declare const processResponse: <T>(responseOrError: AxiosResponse<any> | ApiError, log?: boolean) => StandardResponse<T>;
|
|
310
348
|
|
|
311
349
|
declare function useApi<T extends {
|
|
312
350
|
id?: string | number;
|
|
@@ -338,4 +376,4 @@ declare function useApi<T extends {
|
|
|
338
376
|
};
|
|
339
377
|
};
|
|
340
378
|
|
|
341
|
-
export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
|
|
379
|
+
export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type Logger, type Middleware, type MiddlewareContext, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosProgressEvent, AxiosInstance, Method } from 'axios';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -35,28 +35,49 @@ interface ApiError {
|
|
|
35
35
|
errors?: ValidationError[];
|
|
36
36
|
requestId?: string;
|
|
37
37
|
}
|
|
38
|
-
/**
|
|
39
|
-
* يمثل مجموعة التوكنات التي يتم إدارتها.
|
|
40
|
-
*/
|
|
41
38
|
interface Tokens {
|
|
42
39
|
accessToken: string | null;
|
|
43
40
|
refreshToken: string | null;
|
|
44
41
|
expiresAt?: number;
|
|
45
42
|
tokenType?: string;
|
|
46
43
|
}
|
|
47
|
-
/**
|
|
48
|
-
* واجهة لمدير التوكنات، تسمح بفصل منطق تخزين التوكن.
|
|
49
|
-
* يمكن للمستخدم توفير تطبيق لهذه الواجهة (e.g., LocalStorage, Cookies).
|
|
50
|
-
*/
|
|
51
44
|
interface TokenManager {
|
|
52
45
|
getTokens(): Promise<Tokens>;
|
|
53
46
|
setTokens(tokens: Tokens): Promise<void>;
|
|
54
47
|
clearTokens(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* دالة لتحديد سياق التشغيل.
|
|
50
|
+
* true إذا كانت التوكنات في كوكيز httpOnly (الوضع الآمن).
|
|
51
|
+
* false إذا كانت في مكان يمكن للعميل الوصول إليه (للتطبيقات غير Next.js).
|
|
52
|
+
*/
|
|
55
53
|
isHttpOnly(): boolean;
|
|
56
54
|
}
|
|
57
55
|
/**
|
|
58
|
-
*
|
|
56
|
+
* واجهة لـ Logger مخصص. متوافقة مع `console`.
|
|
59
57
|
*/
|
|
58
|
+
interface Logger {
|
|
59
|
+
log(message?: any, ...optionalParams: any[]): void;
|
|
60
|
+
info(message?: any, ...optionalParams: any[]): void;
|
|
61
|
+
warn(message?: any, ...optionalParams: any[]): void;
|
|
62
|
+
error(message?: any, ...optionalParams: any[]): void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* سياق البرمجيات الوسيطة الذي يتم تمريره لكل دالة.
|
|
66
|
+
*/
|
|
67
|
+
interface MiddlewareContext {
|
|
68
|
+
req: InternalAxiosRequestConfig;
|
|
69
|
+
res?: AxiosResponse;
|
|
70
|
+
error?: any;
|
|
71
|
+
logger: Logger;
|
|
72
|
+
custom?: Record<string, any>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* دالة برمجية وسيطة (Middleware Function).
|
|
76
|
+
*/
|
|
77
|
+
type Middleware = (context: MiddlewareContext, next: () => Promise<void>) => Promise<void>;
|
|
78
|
+
interface RequestConfig extends AxiosRequestConfig {
|
|
79
|
+
isPublic?: boolean;
|
|
80
|
+
}
|
|
60
81
|
interface RequestConfig extends AxiosRequestConfig {
|
|
61
82
|
cancelTokenKey?: string;
|
|
62
83
|
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
|
@@ -113,7 +134,7 @@ interface RefreshTokenConfig {
|
|
|
113
134
|
};
|
|
114
135
|
}
|
|
115
136
|
/**
|
|
116
|
-
* الواجهة الرئيسية لتهيئة عميل الـ API.
|
|
137
|
+
* الواجهة الرئيسية لتهيئة عميل الـ API (محدثة بالكامل).
|
|
117
138
|
*/
|
|
118
139
|
interface ApiClientConfig {
|
|
119
140
|
baseURL?: string;
|
|
@@ -121,13 +142,16 @@ interface ApiClientConfig {
|
|
|
121
142
|
timeout?: number;
|
|
122
143
|
headers?: Record<string, string>;
|
|
123
144
|
withCredentials?: boolean;
|
|
124
|
-
responseType?: ResponseType;
|
|
125
|
-
/**
|
|
126
|
-
* إعدادات مخصصة لعملية تجديد التوكن.
|
|
127
|
-
* إذا لم يتم توفيرها، ستتوقف محاولات التجديد التلقائي.
|
|
128
|
-
*/
|
|
129
145
|
refreshTokenConfig?: RefreshTokenConfig;
|
|
130
146
|
onRefreshError?: (error: any) => void;
|
|
147
|
+
/**
|
|
148
|
+
* ✨ NEW: Logger مخصص. الافتراضي هو `console`.
|
|
149
|
+
*/
|
|
150
|
+
logger?: Logger;
|
|
151
|
+
/**
|
|
152
|
+
* ✨ NEW: مصفوفة من البرمجيات الوسيطة (Middleware) لتشغيلها مع كل طلب.
|
|
153
|
+
*/
|
|
154
|
+
middleware?: Middleware[];
|
|
131
155
|
}
|
|
132
156
|
/**
|
|
133
157
|
* يمثل بنية الاستجابة القياسية من الـ API.
|
|
@@ -214,12 +238,25 @@ interface UseApiConfig<T> {
|
|
|
214
238
|
|
|
215
239
|
/**
|
|
216
240
|
* @file src/core/client.ts
|
|
217
|
-
* @description
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
241
|
+
* @description This is the heart of the API client library.
|
|
242
|
+
* The `createApiClient` function constructs and configures a sophisticated Axios instance.
|
|
243
|
+
* It features intelligent, security-first token management, a flexible middleware system,
|
|
244
|
+
* and customizable logging, all designed to work seamlessly in modern web frameworks like Next.js.
|
|
221
245
|
*/
|
|
222
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Creates and configures a new Axios instance with advanced features.
|
|
249
|
+
*
|
|
250
|
+
* This factory function is the central entry point of the library. It sets up
|
|
251
|
+
* request and response interceptors to handle:
|
|
252
|
+
* - Secure token management (supporting httpOnly and client-side storage).
|
|
253
|
+
* - A flexible middleware pipeline for custom logic.
|
|
254
|
+
* - Centralized logging for observability.
|
|
255
|
+
* - Automatic token refresh for client-side scenarios.
|
|
256
|
+
*
|
|
257
|
+
* @param {ApiClientConfig} config - The configuration object for the API client.
|
|
258
|
+
* @returns {AxiosInstance} A fully configured Axios instance ready for use.
|
|
259
|
+
*/
|
|
223
260
|
declare function createApiClient(config: ApiClientConfig): AxiosInstance;
|
|
224
261
|
|
|
225
262
|
type CrudRequestConfig = RequestConfig & ActionOptions;
|
|
@@ -283,6 +320,7 @@ declare function createApiActions<TActions extends Record<string, {
|
|
|
283
320
|
endpoint: string;
|
|
284
321
|
requestType: any;
|
|
285
322
|
responseType: any;
|
|
323
|
+
log?: boolean;
|
|
286
324
|
}>>(axiosInstance: AxiosInstance, actionsConfig: TActions): {
|
|
287
325
|
[K in keyof TActions]: ApiAction<TActions[K]['requestType'], TActions[K]['responseType']>;
|
|
288
326
|
};
|
|
@@ -306,7 +344,7 @@ declare const cacheManager: CacheManager;
|
|
|
306
344
|
* @param responseOrError The raw Axios response or a pre-processed ApiError.
|
|
307
345
|
* @returns A standardized `StandardResponse` object with direct access to `.data`.
|
|
308
346
|
*/
|
|
309
|
-
declare const processResponse: <T>(responseOrError: AxiosResponse<any> | ApiError) => StandardResponse<T>;
|
|
347
|
+
declare const processResponse: <T>(responseOrError: AxiosResponse<any> | ApiError, log?: boolean) => StandardResponse<T>;
|
|
310
348
|
|
|
311
349
|
declare function useApi<T extends {
|
|
312
350
|
id?: string | number;
|
|
@@ -338,4 +376,4 @@ declare function useApi<T extends {
|
|
|
338
376
|
};
|
|
339
377
|
};
|
|
340
378
|
|
|
341
|
-
export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
|
|
379
|
+
export { type ActionOptions, type ApiClientConfig, type ApiError, type ApiResponse, type Logger, type Middleware, type MiddlewareContext, type PaginateQueryOptions, type PaginationMeta, type QueryOptions, type RefreshTokenConfig, type RequestConfig, type StandardResponse, type TokenManager, type Tokens, type UseApiConfig, type ValidationError, buildPaginateQuery, cacheManager, createApiActions, createApiClient, createApiServices, processResponse, useApi };
|
package/dist/index.js
CHANGED
|
@@ -43,10 +43,20 @@ module.exports = __toCommonJS(index_exports);
|
|
|
43
43
|
// src/core/client.ts
|
|
44
44
|
var import_axios = __toESM(require("axios"));
|
|
45
45
|
var import_uuid = require("uuid");
|
|
46
|
-
async function
|
|
46
|
+
async function runMiddleware(context, middlewares = []) {
|
|
47
|
+
const run = async (index) => {
|
|
48
|
+
if (index >= middlewares.length) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const middleware = middlewares[index];
|
|
52
|
+
await middleware(context, () => run(index + 1));
|
|
53
|
+
};
|
|
54
|
+
await run(0);
|
|
55
|
+
}
|
|
56
|
+
async function refreshToken(config, tokenManager, logger) {
|
|
47
57
|
const { refreshTokenConfig } = config;
|
|
48
58
|
if (!refreshTokenConfig) {
|
|
49
|
-
|
|
59
|
+
logger.warn("[API Core] Token refresh is disabled: `refreshTokenConfig` is not provided.");
|
|
50
60
|
await tokenManager.clearTokens();
|
|
51
61
|
return null;
|
|
52
62
|
}
|
|
@@ -58,6 +68,7 @@ async function refreshToken(config, tokenManager) {
|
|
|
58
68
|
const { path, buildRequestBody, buildRequestHeaders, extractTokens } = refreshTokenConfig;
|
|
59
69
|
const requestBody = buildRequestBody ? buildRequestBody(currentTokens.refreshToken) : { refresh_token: currentTokens.refreshToken };
|
|
60
70
|
const requestHeaders = buildRequestHeaders ? buildRequestHeaders(currentTokens) : {};
|
|
71
|
+
logger.info(`[API Core] Attempting to refresh token at path: ${path}`);
|
|
61
72
|
const response = await import_axios.default.post(
|
|
62
73
|
`${config.baseURL}${path}`,
|
|
63
74
|
requestBody,
|
|
@@ -73,15 +84,14 @@ async function refreshToken(config, tokenManager) {
|
|
|
73
84
|
const newTokens = {
|
|
74
85
|
accessToken: extracted.accessToken,
|
|
75
86
|
refreshToken: extracted.refreshToken || currentTokens.refreshToken,
|
|
76
|
-
// احتفظ بالقديم إذا لم يأتِ جديد
|
|
77
87
|
expiresAt: Date.now() + extracted.expiresIn * 1e3,
|
|
78
88
|
tokenType: extracted.tokenType || "Bearer"
|
|
79
89
|
};
|
|
80
90
|
await tokenManager.setTokens(newTokens);
|
|
81
|
-
|
|
91
|
+
logger.info("[API Core] Tokens refreshed successfully.");
|
|
82
92
|
return newTokens;
|
|
83
93
|
} catch (err) {
|
|
84
|
-
|
|
94
|
+
logger.error("[API Core] Failed to refresh token.", err.response?.data || err.message);
|
|
85
95
|
if (config.onRefreshError) {
|
|
86
96
|
config.onRefreshError(err);
|
|
87
97
|
}
|
|
@@ -95,7 +105,9 @@ function createApiClient(config) {
|
|
|
95
105
|
tokenManager,
|
|
96
106
|
timeout = 15e3,
|
|
97
107
|
headers = {},
|
|
98
|
-
withCredentials = false
|
|
108
|
+
withCredentials = false,
|
|
109
|
+
middleware = [],
|
|
110
|
+
logger = console
|
|
99
111
|
} = config;
|
|
100
112
|
const axiosInstance = import_axios.default.create({
|
|
101
113
|
baseURL,
|
|
@@ -106,66 +118,76 @@ function createApiClient(config) {
|
|
|
106
118
|
let isRefreshing = false;
|
|
107
119
|
let failedQueue = [];
|
|
108
120
|
const processQueue = (error, token = null) => {
|
|
109
|
-
failedQueue.forEach((prom) =>
|
|
110
|
-
if (error) {
|
|
111
|
-
prom.reject(error);
|
|
112
|
-
} else {
|
|
113
|
-
prom.resolve(token);
|
|
114
|
-
}
|
|
115
|
-
});
|
|
121
|
+
failedQueue.forEach((prom) => error ? prom.reject(error) : prom.resolve(token));
|
|
116
122
|
failedQueue = [];
|
|
117
123
|
};
|
|
118
124
|
axiosInstance.interceptors.request.use(async (req) => {
|
|
119
125
|
req.headers["X-Request-ID"] = (0, import_uuid.v4)();
|
|
126
|
+
logger.info(`[Request] > ${req.method?.toUpperCase()} ${req.url}`, { id: req.headers["X-Request-ID"] });
|
|
127
|
+
const context = { req, logger, custom: {} };
|
|
128
|
+
await runMiddleware(context, middleware);
|
|
120
129
|
if (req.isPublic) {
|
|
121
130
|
return req;
|
|
122
131
|
}
|
|
132
|
+
if (tokenManager.isHttpOnly()) {
|
|
133
|
+
return req;
|
|
134
|
+
}
|
|
123
135
|
let tokens = await tokenManager.getTokens();
|
|
124
136
|
const now = Date.now();
|
|
125
137
|
const tokenBuffer = 60 * 1e3;
|
|
126
138
|
if (tokens.accessToken && tokens.expiresAt && tokens.expiresAt - now < tokenBuffer && !isRefreshing) {
|
|
127
139
|
if (config.refreshTokenConfig) {
|
|
128
|
-
|
|
140
|
+
logger.info("[API Core] Proactive token refresh initiated.");
|
|
129
141
|
isRefreshing = true;
|
|
130
142
|
try {
|
|
131
|
-
const newTokens = await refreshToken(config, tokenManager);
|
|
143
|
+
const newTokens = await refreshToken(config, tokenManager, logger);
|
|
132
144
|
if (newTokens) tokens = newTokens;
|
|
133
145
|
} finally {
|
|
134
146
|
isRefreshing = false;
|
|
135
147
|
}
|
|
136
148
|
}
|
|
137
149
|
}
|
|
138
|
-
if (tokens.accessToken
|
|
150
|
+
if (tokens.accessToken) {
|
|
139
151
|
req.headers.Authorization = `${tokens.tokenType || "Bearer"} ${tokens.accessToken}`;
|
|
140
152
|
}
|
|
141
153
|
return req;
|
|
142
|
-
}
|
|
154
|
+
});
|
|
143
155
|
axiosInstance.interceptors.response.use(
|
|
144
|
-
(
|
|
156
|
+
async (res) => {
|
|
157
|
+
logger.info(`[Response] < ${res.config.method?.toUpperCase()} ${res.config.url}`, { id: res.config.headers["X-Request-ID"], status: res.status });
|
|
158
|
+
const context = { req: res.config, res, logger, custom: {} };
|
|
159
|
+
await runMiddleware(context, middleware);
|
|
160
|
+
return res;
|
|
161
|
+
},
|
|
145
162
|
async (error) => {
|
|
146
163
|
const originalRequest = error.config;
|
|
147
|
-
|
|
164
|
+
logger.error(`[Response Error] < ${originalRequest.method?.toUpperCase()} ${originalRequest.url}`, { id: originalRequest.headers?.["X-Request-ID"], status: error.response?.status, error: error.message });
|
|
165
|
+
const context = { req: originalRequest, error, logger, custom: {} };
|
|
166
|
+
await runMiddleware(context, middleware);
|
|
167
|
+
const isHttpOnlyMode = tokenManager.isHttpOnly();
|
|
168
|
+
const canAttemptRefresh = error.response?.status === 401 && !originalRequest._retry && config.refreshTokenConfig;
|
|
169
|
+
if (isHttpOnlyMode && canAttemptRefresh) {
|
|
170
|
+
logger.error("[API Core] Fatal: Received 401 in httpOnly mode. Token refresh must be handled by the server-side proxy. The request will not be retried from the client.");
|
|
171
|
+
return Promise.reject(error);
|
|
172
|
+
}
|
|
173
|
+
if (!isHttpOnlyMode && canAttemptRefresh) {
|
|
148
174
|
if (isRefreshing) {
|
|
149
175
|
return new Promise((resolve, reject) => {
|
|
150
176
|
failedQueue.push({ resolve, reject });
|
|
151
177
|
}).then((token) => {
|
|
152
|
-
|
|
153
|
-
originalRequest.headers["Authorization"] = `Bearer ${token}`;
|
|
154
|
-
}
|
|
178
|
+
originalRequest.headers["Authorization"] = `Bearer ${token}`;
|
|
155
179
|
return axiosInstance(originalRequest);
|
|
156
180
|
});
|
|
157
181
|
}
|
|
158
182
|
originalRequest._retry = true;
|
|
159
183
|
isRefreshing = true;
|
|
160
184
|
try {
|
|
161
|
-
const newTokens = await refreshToken(config, tokenManager);
|
|
185
|
+
const newTokens = await refreshToken(config, tokenManager, logger);
|
|
162
186
|
if (!newTokens || !newTokens.accessToken) {
|
|
163
187
|
throw new Error("Token refresh failed to produce a new access token.");
|
|
164
188
|
}
|
|
165
189
|
processQueue(null, newTokens.accessToken);
|
|
166
|
-
|
|
167
|
-
originalRequest.headers["Authorization"] = `${newTokens.tokenType || "Bearer"} ${newTokens.accessToken}`;
|
|
168
|
-
}
|
|
190
|
+
originalRequest.headers["Authorization"] = `${newTokens.tokenType || "Bearer"} ${newTokens.accessToken}`;
|
|
169
191
|
return axiosInstance(originalRequest);
|
|
170
192
|
} catch (refreshError) {
|
|
171
193
|
processQueue(refreshError, null);
|
|
@@ -174,13 +196,7 @@ function createApiClient(config) {
|
|
|
174
196
|
isRefreshing = false;
|
|
175
197
|
}
|
|
176
198
|
}
|
|
177
|
-
|
|
178
|
-
message: error.response?.data?.message || error.message,
|
|
179
|
-
status: error.response?.status || 500,
|
|
180
|
-
errors: error.response?.data?.errors,
|
|
181
|
-
requestId: originalRequest.headers?.["X-Request-ID"]
|
|
182
|
-
};
|
|
183
|
-
return Promise.reject(enhancedError);
|
|
199
|
+
return Promise.reject(error);
|
|
184
200
|
}
|
|
185
201
|
);
|
|
186
202
|
return axiosInstance;
|
|
@@ -222,8 +238,10 @@ function isAxiosResponse(obj) {
|
|
|
222
238
|
}
|
|
223
239
|
|
|
224
240
|
// src/core/processor.ts
|
|
225
|
-
var processResponse = (responseOrError) => {
|
|
241
|
+
var processResponse = (responseOrError, log) => {
|
|
226
242
|
if (isApiError(responseOrError)) {
|
|
243
|
+
log && console.log(`****[ API ERROR PROCESS RESPONSE ]: ***
|
|
244
|
+
${responseOrError} *** `);
|
|
227
245
|
return {
|
|
228
246
|
data: null,
|
|
229
247
|
rawResponse: void 0,
|
|
@@ -235,15 +253,17 @@ var processResponse = (responseOrError) => {
|
|
|
235
253
|
};
|
|
236
254
|
}
|
|
237
255
|
if (isAxiosResponse(responseOrError)) {
|
|
256
|
+
log && console.log(`****[ API IS SCSS PROCESS RESPONSE ]: ***
|
|
257
|
+
${responseOrError} *** `);
|
|
238
258
|
const rawData = responseOrError.data;
|
|
239
259
|
const isWrappedResponse = rawData && typeof rawData.success === "boolean" && rawData.data !== void 0;
|
|
260
|
+
log && console.log(`12345[ API IS WRAPPED DATA PROCESS RESPONSE ]: ***
|
|
261
|
+
${isWrappedResponse} *** `);
|
|
240
262
|
const finalData = isWrappedResponse ? rawData.data : rawData;
|
|
241
263
|
const message = isWrappedResponse ? rawData.message : "Request successful.";
|
|
242
264
|
return {
|
|
243
265
|
data: finalData,
|
|
244
|
-
// <-- وصول مباشر للبيانات النهائية!
|
|
245
266
|
rawResponse: rawData,
|
|
246
|
-
// احتفظ بالاستجابة الكاملة إذا احتجت إليها
|
|
247
267
|
loading: false,
|
|
248
268
|
success: true,
|
|
249
269
|
error: null,
|
|
@@ -251,6 +271,7 @@ var processResponse = (responseOrError) => {
|
|
|
251
271
|
validationErrors: []
|
|
252
272
|
};
|
|
253
273
|
}
|
|
274
|
+
log && console.log(`****[ API STATUS 500 ]: *** ${responseOrError} *** `);
|
|
254
275
|
return {
|
|
255
276
|
data: null,
|
|
256
277
|
rawResponse: void 0,
|
|
@@ -350,19 +371,22 @@ function createApiServices(axiosInstance, endpoint) {
|
|
|
350
371
|
}
|
|
351
372
|
|
|
352
373
|
// src/services/actions.ts
|
|
353
|
-
function createAction(axiosInstance, method, endpoint) {
|
|
374
|
+
function createAction(axiosInstance, method, endpoint, log) {
|
|
354
375
|
return async (payload, config) => {
|
|
376
|
+
log && console.log(`*[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]: ${endpoint} **** [${payload}]** `);
|
|
355
377
|
try {
|
|
378
|
+
log && console.log(`**[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]:${endpoint} **** [action try req]** `);
|
|
356
379
|
const response = await axiosInstance.request({
|
|
357
|
-
// <--- غيرنا النوع إلى any
|
|
358
380
|
url: endpoint,
|
|
359
381
|
method,
|
|
360
382
|
...method.toUpperCase() === "GET" ? { params: payload } : { data: payload },
|
|
361
383
|
...config
|
|
362
384
|
});
|
|
363
|
-
|
|
385
|
+
log && console.log(`***[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]: ${endpoint} ***
|
|
386
|
+
${response}*** `);
|
|
387
|
+
return processResponse(response, log);
|
|
364
388
|
} catch (error) {
|
|
365
|
-
return processResponse(error);
|
|
389
|
+
return processResponse(error, log);
|
|
366
390
|
}
|
|
367
391
|
};
|
|
368
392
|
}
|
|
@@ -370,8 +394,8 @@ function createApiActions(axiosInstance, actionsConfig) {
|
|
|
370
394
|
const actions = {};
|
|
371
395
|
for (const actionName in actionsConfig) {
|
|
372
396
|
if (Object.prototype.hasOwnProperty.call(actionsConfig, actionName)) {
|
|
373
|
-
const { method, endpoint } = actionsConfig[actionName];
|
|
374
|
-
actions[actionName] = createAction(axiosInstance, method, endpoint);
|
|
397
|
+
const { method, endpoint, log } = actionsConfig[actionName];
|
|
398
|
+
actions[actionName] = createAction(axiosInstance, method, endpoint, log);
|
|
375
399
|
}
|
|
376
400
|
}
|
|
377
401
|
return actions;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
// src/core/client.ts
|
|
2
2
|
import axios from "axios";
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
|
-
async function
|
|
4
|
+
async function runMiddleware(context, middlewares = []) {
|
|
5
|
+
const run = async (index) => {
|
|
6
|
+
if (index >= middlewares.length) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const middleware = middlewares[index];
|
|
10
|
+
await middleware(context, () => run(index + 1));
|
|
11
|
+
};
|
|
12
|
+
await run(0);
|
|
13
|
+
}
|
|
14
|
+
async function refreshToken(config, tokenManager, logger) {
|
|
5
15
|
const { refreshTokenConfig } = config;
|
|
6
16
|
if (!refreshTokenConfig) {
|
|
7
|
-
|
|
17
|
+
logger.warn("[API Core] Token refresh is disabled: `refreshTokenConfig` is not provided.");
|
|
8
18
|
await tokenManager.clearTokens();
|
|
9
19
|
return null;
|
|
10
20
|
}
|
|
@@ -16,6 +26,7 @@ async function refreshToken(config, tokenManager) {
|
|
|
16
26
|
const { path, buildRequestBody, buildRequestHeaders, extractTokens } = refreshTokenConfig;
|
|
17
27
|
const requestBody = buildRequestBody ? buildRequestBody(currentTokens.refreshToken) : { refresh_token: currentTokens.refreshToken };
|
|
18
28
|
const requestHeaders = buildRequestHeaders ? buildRequestHeaders(currentTokens) : {};
|
|
29
|
+
logger.info(`[API Core] Attempting to refresh token at path: ${path}`);
|
|
19
30
|
const response = await axios.post(
|
|
20
31
|
`${config.baseURL}${path}`,
|
|
21
32
|
requestBody,
|
|
@@ -31,15 +42,14 @@ async function refreshToken(config, tokenManager) {
|
|
|
31
42
|
const newTokens = {
|
|
32
43
|
accessToken: extracted.accessToken,
|
|
33
44
|
refreshToken: extracted.refreshToken || currentTokens.refreshToken,
|
|
34
|
-
// احتفظ بالقديم إذا لم يأتِ جديد
|
|
35
45
|
expiresAt: Date.now() + extracted.expiresIn * 1e3,
|
|
36
46
|
tokenType: extracted.tokenType || "Bearer"
|
|
37
47
|
};
|
|
38
48
|
await tokenManager.setTokens(newTokens);
|
|
39
|
-
|
|
49
|
+
logger.info("[API Core] Tokens refreshed successfully.");
|
|
40
50
|
return newTokens;
|
|
41
51
|
} catch (err) {
|
|
42
|
-
|
|
52
|
+
logger.error("[API Core] Failed to refresh token.", err.response?.data || err.message);
|
|
43
53
|
if (config.onRefreshError) {
|
|
44
54
|
config.onRefreshError(err);
|
|
45
55
|
}
|
|
@@ -53,7 +63,9 @@ function createApiClient(config) {
|
|
|
53
63
|
tokenManager,
|
|
54
64
|
timeout = 15e3,
|
|
55
65
|
headers = {},
|
|
56
|
-
withCredentials = false
|
|
66
|
+
withCredentials = false,
|
|
67
|
+
middleware = [],
|
|
68
|
+
logger = console
|
|
57
69
|
} = config;
|
|
58
70
|
const axiosInstance = axios.create({
|
|
59
71
|
baseURL,
|
|
@@ -64,66 +76,76 @@ function createApiClient(config) {
|
|
|
64
76
|
let isRefreshing = false;
|
|
65
77
|
let failedQueue = [];
|
|
66
78
|
const processQueue = (error, token = null) => {
|
|
67
|
-
failedQueue.forEach((prom) =>
|
|
68
|
-
if (error) {
|
|
69
|
-
prom.reject(error);
|
|
70
|
-
} else {
|
|
71
|
-
prom.resolve(token);
|
|
72
|
-
}
|
|
73
|
-
});
|
|
79
|
+
failedQueue.forEach((prom) => error ? prom.reject(error) : prom.resolve(token));
|
|
74
80
|
failedQueue = [];
|
|
75
81
|
};
|
|
76
82
|
axiosInstance.interceptors.request.use(async (req) => {
|
|
77
83
|
req.headers["X-Request-ID"] = uuidv4();
|
|
84
|
+
logger.info(`[Request] > ${req.method?.toUpperCase()} ${req.url}`, { id: req.headers["X-Request-ID"] });
|
|
85
|
+
const context = { req, logger, custom: {} };
|
|
86
|
+
await runMiddleware(context, middleware);
|
|
78
87
|
if (req.isPublic) {
|
|
79
88
|
return req;
|
|
80
89
|
}
|
|
90
|
+
if (tokenManager.isHttpOnly()) {
|
|
91
|
+
return req;
|
|
92
|
+
}
|
|
81
93
|
let tokens = await tokenManager.getTokens();
|
|
82
94
|
const now = Date.now();
|
|
83
95
|
const tokenBuffer = 60 * 1e3;
|
|
84
96
|
if (tokens.accessToken && tokens.expiresAt && tokens.expiresAt - now < tokenBuffer && !isRefreshing) {
|
|
85
97
|
if (config.refreshTokenConfig) {
|
|
86
|
-
|
|
98
|
+
logger.info("[API Core] Proactive token refresh initiated.");
|
|
87
99
|
isRefreshing = true;
|
|
88
100
|
try {
|
|
89
|
-
const newTokens = await refreshToken(config, tokenManager);
|
|
101
|
+
const newTokens = await refreshToken(config, tokenManager, logger);
|
|
90
102
|
if (newTokens) tokens = newTokens;
|
|
91
103
|
} finally {
|
|
92
104
|
isRefreshing = false;
|
|
93
105
|
}
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
|
-
if (tokens.accessToken
|
|
108
|
+
if (tokens.accessToken) {
|
|
97
109
|
req.headers.Authorization = `${tokens.tokenType || "Bearer"} ${tokens.accessToken}`;
|
|
98
110
|
}
|
|
99
111
|
return req;
|
|
100
|
-
}
|
|
112
|
+
});
|
|
101
113
|
axiosInstance.interceptors.response.use(
|
|
102
|
-
(
|
|
114
|
+
async (res) => {
|
|
115
|
+
logger.info(`[Response] < ${res.config.method?.toUpperCase()} ${res.config.url}`, { id: res.config.headers["X-Request-ID"], status: res.status });
|
|
116
|
+
const context = { req: res.config, res, logger, custom: {} };
|
|
117
|
+
await runMiddleware(context, middleware);
|
|
118
|
+
return res;
|
|
119
|
+
},
|
|
103
120
|
async (error) => {
|
|
104
121
|
const originalRequest = error.config;
|
|
105
|
-
|
|
122
|
+
logger.error(`[Response Error] < ${originalRequest.method?.toUpperCase()} ${originalRequest.url}`, { id: originalRequest.headers?.["X-Request-ID"], status: error.response?.status, error: error.message });
|
|
123
|
+
const context = { req: originalRequest, error, logger, custom: {} };
|
|
124
|
+
await runMiddleware(context, middleware);
|
|
125
|
+
const isHttpOnlyMode = tokenManager.isHttpOnly();
|
|
126
|
+
const canAttemptRefresh = error.response?.status === 401 && !originalRequest._retry && config.refreshTokenConfig;
|
|
127
|
+
if (isHttpOnlyMode && canAttemptRefresh) {
|
|
128
|
+
logger.error("[API Core] Fatal: Received 401 in httpOnly mode. Token refresh must be handled by the server-side proxy. The request will not be retried from the client.");
|
|
129
|
+
return Promise.reject(error);
|
|
130
|
+
}
|
|
131
|
+
if (!isHttpOnlyMode && canAttemptRefresh) {
|
|
106
132
|
if (isRefreshing) {
|
|
107
133
|
return new Promise((resolve, reject) => {
|
|
108
134
|
failedQueue.push({ resolve, reject });
|
|
109
135
|
}).then((token) => {
|
|
110
|
-
|
|
111
|
-
originalRequest.headers["Authorization"] = `Bearer ${token}`;
|
|
112
|
-
}
|
|
136
|
+
originalRequest.headers["Authorization"] = `Bearer ${token}`;
|
|
113
137
|
return axiosInstance(originalRequest);
|
|
114
138
|
});
|
|
115
139
|
}
|
|
116
140
|
originalRequest._retry = true;
|
|
117
141
|
isRefreshing = true;
|
|
118
142
|
try {
|
|
119
|
-
const newTokens = await refreshToken(config, tokenManager);
|
|
143
|
+
const newTokens = await refreshToken(config, tokenManager, logger);
|
|
120
144
|
if (!newTokens || !newTokens.accessToken) {
|
|
121
145
|
throw new Error("Token refresh failed to produce a new access token.");
|
|
122
146
|
}
|
|
123
147
|
processQueue(null, newTokens.accessToken);
|
|
124
|
-
|
|
125
|
-
originalRequest.headers["Authorization"] = `${newTokens.tokenType || "Bearer"} ${newTokens.accessToken}`;
|
|
126
|
-
}
|
|
148
|
+
originalRequest.headers["Authorization"] = `${newTokens.tokenType || "Bearer"} ${newTokens.accessToken}`;
|
|
127
149
|
return axiosInstance(originalRequest);
|
|
128
150
|
} catch (refreshError) {
|
|
129
151
|
processQueue(refreshError, null);
|
|
@@ -132,13 +154,7 @@ function createApiClient(config) {
|
|
|
132
154
|
isRefreshing = false;
|
|
133
155
|
}
|
|
134
156
|
}
|
|
135
|
-
|
|
136
|
-
message: error.response?.data?.message || error.message,
|
|
137
|
-
status: error.response?.status || 500,
|
|
138
|
-
errors: error.response?.data?.errors,
|
|
139
|
-
requestId: originalRequest.headers?.["X-Request-ID"]
|
|
140
|
-
};
|
|
141
|
-
return Promise.reject(enhancedError);
|
|
157
|
+
return Promise.reject(error);
|
|
142
158
|
}
|
|
143
159
|
);
|
|
144
160
|
return axiosInstance;
|
|
@@ -180,8 +196,10 @@ function isAxiosResponse(obj) {
|
|
|
180
196
|
}
|
|
181
197
|
|
|
182
198
|
// src/core/processor.ts
|
|
183
|
-
var processResponse = (responseOrError) => {
|
|
199
|
+
var processResponse = (responseOrError, log) => {
|
|
184
200
|
if (isApiError(responseOrError)) {
|
|
201
|
+
log && console.log(`****[ API ERROR PROCESS RESPONSE ]: ***
|
|
202
|
+
${responseOrError} *** `);
|
|
185
203
|
return {
|
|
186
204
|
data: null,
|
|
187
205
|
rawResponse: void 0,
|
|
@@ -193,15 +211,17 @@ var processResponse = (responseOrError) => {
|
|
|
193
211
|
};
|
|
194
212
|
}
|
|
195
213
|
if (isAxiosResponse(responseOrError)) {
|
|
214
|
+
log && console.log(`****[ API IS SCSS PROCESS RESPONSE ]: ***
|
|
215
|
+
${responseOrError} *** `);
|
|
196
216
|
const rawData = responseOrError.data;
|
|
197
217
|
const isWrappedResponse = rawData && typeof rawData.success === "boolean" && rawData.data !== void 0;
|
|
218
|
+
log && console.log(`12345[ API IS WRAPPED DATA PROCESS RESPONSE ]: ***
|
|
219
|
+
${isWrappedResponse} *** `);
|
|
198
220
|
const finalData = isWrappedResponse ? rawData.data : rawData;
|
|
199
221
|
const message = isWrappedResponse ? rawData.message : "Request successful.";
|
|
200
222
|
return {
|
|
201
223
|
data: finalData,
|
|
202
|
-
// <-- وصول مباشر للبيانات النهائية!
|
|
203
224
|
rawResponse: rawData,
|
|
204
|
-
// احتفظ بالاستجابة الكاملة إذا احتجت إليها
|
|
205
225
|
loading: false,
|
|
206
226
|
success: true,
|
|
207
227
|
error: null,
|
|
@@ -209,6 +229,7 @@ var processResponse = (responseOrError) => {
|
|
|
209
229
|
validationErrors: []
|
|
210
230
|
};
|
|
211
231
|
}
|
|
232
|
+
log && console.log(`****[ API STATUS 500 ]: *** ${responseOrError} *** `);
|
|
212
233
|
return {
|
|
213
234
|
data: null,
|
|
214
235
|
rawResponse: void 0,
|
|
@@ -308,19 +329,22 @@ function createApiServices(axiosInstance, endpoint) {
|
|
|
308
329
|
}
|
|
309
330
|
|
|
310
331
|
// src/services/actions.ts
|
|
311
|
-
function createAction(axiosInstance, method, endpoint) {
|
|
332
|
+
function createAction(axiosInstance, method, endpoint, log) {
|
|
312
333
|
return async (payload, config) => {
|
|
334
|
+
log && console.log(`*[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]: ${endpoint} **** [${payload}]** `);
|
|
313
335
|
try {
|
|
336
|
+
log && console.log(`**[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]:${endpoint} **** [action try req]** `);
|
|
314
337
|
const response = await axiosInstance.request({
|
|
315
|
-
// <--- غيرنا النوع إلى any
|
|
316
338
|
url: endpoint,
|
|
317
339
|
method,
|
|
318
340
|
...method.toUpperCase() === "GET" ? { params: payload } : { data: payload },
|
|
319
341
|
...config
|
|
320
342
|
});
|
|
321
|
-
|
|
343
|
+
log && console.log(`***[ ${method.toUpperCase()} ACTION API TO ENDPOINT ]: ${endpoint} ***
|
|
344
|
+
${response}*** `);
|
|
345
|
+
return processResponse(response, log);
|
|
322
346
|
} catch (error) {
|
|
323
|
-
return processResponse(error);
|
|
347
|
+
return processResponse(error, log);
|
|
324
348
|
}
|
|
325
349
|
};
|
|
326
350
|
}
|
|
@@ -328,8 +352,8 @@ function createApiActions(axiosInstance, actionsConfig) {
|
|
|
328
352
|
const actions = {};
|
|
329
353
|
for (const actionName in actionsConfig) {
|
|
330
354
|
if (Object.prototype.hasOwnProperty.call(actionsConfig, actionName)) {
|
|
331
|
-
const { method, endpoint } = actionsConfig[actionName];
|
|
332
|
-
actions[actionName] = createAction(axiosInstance, method, endpoint);
|
|
355
|
+
const { method, endpoint, log } = actionsConfig[actionName];
|
|
356
|
+
actions[actionName] = createAction(axiosInstance, method, endpoint, log);
|
|
333
357
|
}
|
|
334
358
|
}
|
|
335
359
|
return actions;
|
package/package.json
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "api-core-lib",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A flexible and powerful API client library for modern web applications.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
|
-
"types": "dist/index.d.ts",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
10
|
-
"dev": "tsup src/index.ts --format esm,cjs --dts --watch"
|
|
11
|
-
},
|
|
12
|
-
"keywords": [
|
|
13
|
-
"axios",
|
|
14
|
-
"api",
|
|
15
|
-
"react",
|
|
16
|
-
"nextjs",
|
|
17
|
-
"typescript",
|
|
18
|
-
"state-management"
|
|
19
|
-
],
|
|
20
|
-
"author": "Your Name",
|
|
21
|
-
"license": "MIT",
|
|
22
|
-
"peerDependencies": {
|
|
23
|
-
"react": ">=17.0.0"
|
|
24
|
-
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"axios": "^1.6.8",
|
|
27
|
-
"axios-retry": "^4.1.0",
|
|
28
|
-
"uuid": "^9.0.1"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@types/react": "^18.3.2",
|
|
32
|
-
"@types/uuid": "^9.0.8",
|
|
33
|
-
"react": "^18.3.1",
|
|
34
|
-
"tsup": "^8.0.2",
|
|
35
|
-
"typescript": "^5.4.5"
|
|
36
|
-
},
|
|
37
|
-
"files": [
|
|
38
|
-
"dist"
|
|
39
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"name": "api-core-lib",
|
|
3
|
+
"version": "5.5.4",
|
|
4
|
+
"description": "A flexible and powerful API client library for modern web applications.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
10
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"axios",
|
|
14
|
+
"api",
|
|
15
|
+
"react",
|
|
16
|
+
"nextjs",
|
|
17
|
+
"typescript",
|
|
18
|
+
"state-management"
|
|
19
|
+
],
|
|
20
|
+
"author": "Your Name",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": ">=17.0.0"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"axios": "^1.6.8",
|
|
27
|
+
"axios-retry": "^4.1.0",
|
|
28
|
+
"uuid": "^9.0.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/react": "^18.3.2",
|
|
32
|
+
"@types/uuid": "^9.0.8",
|
|
33
|
+
"react": "^18.3.1",
|
|
34
|
+
"tsup": "^8.0.2",
|
|
35
|
+
"typescript": "^5.4.5"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
]
|
|
40
40
|
}
|