import axios from 'axios'; import type { ApiClient } from './types'; import type { AxiosError, AxiosResponse, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios'; import { ApiError } from './errors'; // 直接导入ApiError // 创建API客户端实例的工厂函数 const createApiClientInstance = (config?: Partial): ApiClient => { // 创建axios实例 const instance = axios.create({ baseURL: '/api', // Core层使用默认值,具体配置由Runtime层注入 timeout: 10000, headers: { 'Content-Type': 'application/json' }, withCredentials: true, // 允许跨域携带cookie ...config // 应用传入的配置 }); // 请求拦截器数组 const requestInterceptors: Array = []; // 响应拦截器数组 const responseInterceptors: Array = []; // 添加请求拦截器 const addRequestInterceptor = ( onFulfilled?: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise, onRejected?: (_error: unknown) => unknown ): number => { const handler = instance.interceptors.request.use(onFulfilled, onRejected); requestInterceptors.push(handler); return handler; }; // 添加响应拦截器 const addResponseInterceptor = ( onFulfilled?: (_response: AxiosResponse) => AxiosResponse | Promise, onRejected?: (_error: unknown) => unknown ): number => { const handler = instance.interceptors.response.use(onFulfilled, onRejected); responseInterceptors.push(handler); return handler; }; // 移除请求拦截器 const removeRequestInterceptor = (handler: number): void => { const index = requestInterceptors.indexOf(handler); if (index !== -1) { instance.interceptors.request.eject(handler); requestInterceptors.splice(index, 1); } }; // 移除响应拦截器 const removeResponseInterceptor = (handler: number): void => { const index = responseInterceptors.indexOf(handler); if (index !== -1) { instance.interceptors.response.eject(handler); responseInterceptors.splice(index, 1); } }; // 设置默认配置 const setDefaults = (_config: Partial): void => { Object.assign(instance.defaults, _config); }; // 更新基础URL - 专门用于Runtime层配置 const setBaseURL = (baseURL: string): void => { instance.defaults.baseURL = baseURL; }; // 创建新实例 - 用于跨域请求等特殊场景 const createInstance = (config?: Partial): ApiClient => { // 创建新的axios实例 const newInstance = axios.create({ ...instance.defaults, ...config }); // 为新实例创建拦截器数组 const newRequestInterceptors: Array = []; const newResponseInterceptors: Array = []; // 复制拦截器 requestInterceptors.forEach(handler => { // 由于AxiosInterceptorManager类型定义中没有handlers属性, // 我们使用类型断言来访问内部属性 type RequestHandlerType = { id: number; fulfilled: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig; rejected: (_error: unknown) => unknown; }; type RequestManagerType = { handlers?: Array; }; const requestManager = instance.interceptors.request as unknown as RequestManagerType; const originalInterceptor = requestManager.handlers?.find((h: RequestHandlerType) => h.id === handler); if (originalInterceptor) { const newHandler = newInstance.interceptors.request.use( originalInterceptor.fulfilled, originalInterceptor.rejected ); newRequestInterceptors.push(newHandler); } }); responseInterceptors.forEach(handler => { // 由于AxiosInterceptorManager类型定义中没有handlers属性, // 我们使用类型断言来访问内部属性 type ResponseHandlerType = { id: number; fulfilled: (_response: AxiosResponse) => AxiosResponse; rejected: (_error: AxiosError) => unknown; }; type ResponseManagerType = { handlers?: Array; }; const responseManager = instance.interceptors.response as unknown as ResponseManagerType; const originalInterceptor = responseManager.handlers?.find((h: ResponseHandlerType) => h.id === handler); if (originalInterceptor) { const newHandler = newInstance.interceptors.response.use( originalInterceptor.fulfilled, originalInterceptor.rejected ); newResponseInterceptors.push(newHandler); } }); // 返回一个符合ApiClient接口的对象 return { request: async (config: AxiosRequestConfig): Promise => { try { const response = await newInstance.request(config); return response.data; } catch (error) { // 直接使用ApiError.fromAxiosError静态方法处理错误 return Promise.reject(ApiError.fromAxiosError(error as AxiosError)); } }, get: (url: string, config?: AxiosRequestConfig): Promise => { return newInstance.request({ ...config, method: 'GET', url }).then((res: AxiosResponse) => res.data); }, post: (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return newInstance.request({ ...config, method: 'POST', url, data }).then((res: AxiosResponse) => res.data); }, put: (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return newInstance.request({ ...config, method: 'PUT', url, data }).then((res: AxiosResponse) => res.data); }, delete: (url: string, config?: AxiosRequestConfig): Promise => { return newInstance.request({ ...config, method: 'DELETE', url }).then((res: AxiosResponse) => res.data); }, patch: (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return newInstance.request({ ...config, method: 'PATCH', url, data }).then((res: AxiosResponse) => res.data); }, setDefaults: (_config: Partial): void => { Object.assign(newInstance.defaults, _config); }, setBaseURL: (baseURL: string): void => { newInstance.defaults.baseURL = baseURL; }, createInstance: (newConfig?: Partial): ApiClient => { // 手动处理headers字段的类型转换 const { headers, ...otherDefaults } = newInstance.defaults; const configWithTypedHeaders: Partial = { ...otherDefaults, ...newConfig }; // 只有当headers存在时才添加 if (headers) { // 手动转换headers字段,确保类型安全 const convertedHeaders: Record = {}; Object.entries(headers).forEach(([key, value]) => { if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { convertedHeaders[key] = value; } }); configWithTypedHeaders.headers = convertedHeaders; } return createInstance(configWithTypedHeaders); }, addRequestInterceptor: ( onFulfilled?: (_config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise, onRejected?: (_error: unknown) => unknown ): number => { const handler = newInstance.interceptors.request.use(onFulfilled, onRejected); newRequestInterceptors.push(handler); return handler; }, addResponseInterceptor: ( onFulfilled?: (_response: AxiosResponse) => AxiosResponse | Promise, onRejected?: (_error: unknown) => unknown ): number => { const handler = newInstance.interceptors.response.use(onFulfilled, onRejected); newResponseInterceptors.push(handler); return handler; }, removeRequestInterceptor: (handler: number): void => { const index = newRequestInterceptors.indexOf(handler); if (index !== -1) { newInstance.interceptors.request.eject(handler); newRequestInterceptors.splice(index, 1); } }, removeResponseInterceptor: (handler: number): void => { const index = newResponseInterceptors.indexOf(handler); if (index !== -1) { newInstance.interceptors.response.eject(handler); newResponseInterceptors.splice(index, 1); } } }; }; // 基础请求方法 const request = async (config: AxiosRequestConfig): Promise => { try { const response = await instance.request(config); return response.data; } catch (error) { // 直接使用ApiError.fromAxiosError静态方法处理错误 return Promise.reject(ApiError.fromAxiosError(error as AxiosError)); } }; // HTTP方法简写 const get = (url: string, config?: AxiosRequestConfig): Promise => { return request({ ...config, method: 'GET', url }); }; const post = (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return request({ ...config, method: 'POST', url, data }); }; const put = (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return request({ ...config, method: 'PUT', url, data }); }; const del = (url: string, config?: AxiosRequestConfig): Promise => { return request({ ...config, method: 'DELETE', url }); }; const patch = (url: string, data?: unknown, config?: AxiosRequestConfig): Promise => { return request({ ...config, method: 'PATCH', url, data }); }; return { request, get, post, put, delete: del, patch, setDefaults, setBaseURL, createInstance, addRequestInterceptor, addResponseInterceptor, removeRequestInterceptor, removeResponseInterceptor }; }; // 默认实例(单例) const apiClient = createApiClientInstance(); // 工厂函数 const createApiClient = (config?: Partial) => { return createApiClientInstance(config); }; // 导出API客户端和工厂函数 export { apiClient, createApiClient };