### Install axios-easy Source: https://context7.com/greatauk/axios-easy/llms.txt Install the axios-easy library using your preferred package manager. ```bash pnpm add axios-easy # or npm install axios-easy # or yarn add axios-easy ``` -------------------------------- ### Quick Setup with createRequestClient Factory Source: https://github.com/greatauk/axios-easy/blob/main/skills/use-axios-easy/SKILL.md A factory function that handles all interceptors for quick integration. It simplifies the setup process by providing a pre-configured request client. ```typescript import { createRequestClient } from 'axios-easy/create-request-client'; const { axiosInstance, request } = createRequestClient({ axiosConfig: { baseURL: '...', timeout: 30000 }, defaultRequest: true, defaultResponse: { codeField: 'code', dataField: 'data', successCode: 0 }, authenticate: (instance) => ({ ... }), errorMessage: { handler: (error, networkErrMsg) => { ... } }, setup: (client) => { /* 挂载自定义拦截器或第三方插件 */ }, }); ``` -------------------------------- ### Practical Application Scenario Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Provides an example of how to integrate the interceptor into an application's startup and language switching logic. ```APIDOC ## Practical Application Scenarios ```typescript // Set the global language based on user preferences when the application starts const userLanguage = localStorage.getItem('language') || 'zh'; setGlobalLanguage(userLanguage as 'zh' | 'en'); // Create an interceptor that automatically uses the global language setting const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { message.error(errorMessage); } } ); // When the user switches language function switchLanguage(newLanguage: 'zh' | 'en') { setGlobalLanguage(newLanguage); localStorage.setItem('language', newLanguage); // All subsequent error messages will use the new language } ``` ``` -------------------------------- ### Application Startup Language Setting Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Set the global language based on user preferences stored in local storage when the application starts. ```typescript // 应用启动时根据用户偏好设置全局语言 const userLanguage = localStorage.getItem('language') || 'zh'; setGlobalLanguage(userLanguage as 'zh' | 'en'); // 创建拦截器,自动使用全局语言设置 const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { message.error(errorMessage); } } ); // 用户切换语言时 function switchLanguage(newLanguage: 'zh' | 'en') { setGlobalLanguage(newLanguage); localStorage.setItem('language', newLanguage); // 后续所有请求的错误信息都会使用新语言 } ``` -------------------------------- ### Create Request Client with Axios-Easy Source: https://github.com/greatauk/axios-easy/blob/main/TRAINING.md Demonstrates how to create a pre-configured axios instance using the `createRequestClient` factory function. This includes setting up basic axios configurations, default request and response interceptors, authentication handling, error message display, and custom setup logic. ```typescript // src/utils/request.ts import { createRequestClient } from 'axios-easy/create-request-client'; import type { AxiosError, AxiosResponse } from 'axios'; import { ElMessage, ElMessageBox } from 'element-plus'; // 假设使用 Element Plus // 假设后端接口返回的数据结构 type ApiResponse = { resultCode: 'SUCCESS' | 'FAIL'; data: T; errorCode?: string; errorCodeDes?: string; }; // 和后端约定好的登录失效错误码 const AUTH_ERROR_CODES = ['TOKEN_TIMEOUT', 'KICK_OUT']; const { axiosInstance, request, setGlobalLanguage } = createRequestClient({ // 1. 基础 Axios 配置 axiosConfig: { baseURL: '/api', timeout: 30 * 1000, }, // 2. 开启默认请求拦截器 (处理下载超时、参数规范化) defaultRequest: { extendTimeoutWhenDownload: true, normalizePayload: { trim: true, dropUndefined: true, emptyStringToNull: true }, }, // 3. 配置默认响应拦截器 (解包数据、判断业务成功) defaultResponse: { codeField: 'resultCode', dataField: 'data', successCode: 'SUCCESS', isThrowWhenFail: true, // 业务失败时抛出错误, 进入 catch 块 }, // 4. 配置认证拦截器 (处理 401 和 Token 刷新) authenticate: (instance) => ({ isAuthenticateFailed: (error) => { const errorCode = error.response?.data?.errorCode; return error.response?.status === 401 || (errorCode ? AUTH_ERROR_CODES.includes(errorCode) : false); }, doReAuthenticate: async () => { // 清理用户信息, 跳转登录页 console.log('认证失败, 跳转登录页'); window.location.href = '/login'; }, enableRefreshToken: true, // 启用无感刷新 doRefreshToken: async () => { // 实现刷新 token 的逻辑 const res = await instance.post('/refresh-token', { refreshToken: localStorage.getItem('refresh_token'), }); const { token, refreshToken } = res.data; localStorage.setItem('access_token', token); localStorage.setItem('refresh_token', refreshToken); }, }), // 5. 配置错误消息拦截器 (统一弹窗提示) errorMessage: { handler: (errorResponse, networkErrMsg) => { const errorMessage = errorResponse.data?.errorCodeDes || networkErrMsg || '未知错误'; if (errorResponse.config?.errorMessageMode === 'modal') { ElMessageBox.alert(errorMessage, '错误提示', { type: 'error' }); } else if (errorResponse.config?.errorMessageMode !== 'none') { ElMessage.error(errorMessage); } }, defaultLanguage: 'zh', }, // 6. 自定义设置 (例如: 添加业务 Token) setup: (client) => { client.interceptors.request.use((config) => { const token = localStorage.getItem('access_token'); if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } return config; }); }, }); export default request; export { axiosInstance, setGlobalLanguage }; ``` -------------------------------- ### Create Params Serializer Interceptor for Axios Source: https://context7.com/greatauk/axios-easy/llms.txt Installs a qs-based paramsSerializer on an Axios instance for fine-grained control over query string serialization. The global format is set at install time; individual requests can override it via `qsStringifyArrayFormat` in the request config. ```typescript import axios from 'axios'; import { createParamsSerializerInterceptor } from 'axios-easy/params-serializer-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com' }); const interceptorId = createParamsSerializerInterceptor(instance, { qsStringifyArrayFormat: 'brackets', // global default }); // Uses global 'brackets' format → ?tags[]=frontend&tags[]=backend instance.get('/posts', { params: { tags: ['frontend', 'backend'], page: 1 } }); // Per-request override → ?categories=tech,news instance.get('/articles', { params: { categories: ['tech', 'news'] }, qsStringifyArrayFormat: 'comma', }); // Format comparison for { items: ['a', 'b', 'c'] }: // 'brackets' → items[]=a&items[]=b&items[]=c // 'indices' → items[0]=a&items[1]=b&items[2]=c // 'repeat' → items=a&items=b&items=c // 'comma' → items=a,b,c instance.interceptors.request.eject(interceptorId); ``` -------------------------------- ### Configure Axios Instance with `createRequestClient` Source: https://github.com/greatauk/axios-easy/blob/main/README.md Use `createRequestClient` to set up a configurable Axios instance. This example shows how to configure base URL, response handling, authentication, and error messages. It also demonstrates adding custom request interceptors. ```typescript import type { AxiosError, AxiosResponse } from 'axios'; import { createRequestClient } from 'axios-easy/create-request-client'; /** 假设你的接口返回数据结构如下 */ type ApiResponse = { resultCode: 'SUCCESS' | 'FAIL'; data: T; errorCode?: string; errorCodeDes?: string; }; /** 和后端约定好的登录失效错误码 */ const AUTH_ERROR_CODES = [ 'KICK_OUT', 'LOGIN_REPLACE', 'NOT_TOKEN', 'TOKEN_DEFAULT_ERROR', 'TOKEN_TIMEOUT', ]; const { axiosInstance, request, setGlobalLanguage } = createRequestClient({ axiosConfig: { baseURL: 'https://api.example.com', responseReturn: 'body', errorMessageMode: 'message', timeout: 30 * 1000, }, // 使用 qs 库对请求参数进行序列化,这个一般不需要使用,用于发送 application/x-www-form-urlencoded 格式的数据。 paramsSerializer: false, /** 是否启用默认请求拦截器。true 表示使用默认配置(下载延长超时 & 请求体规范化-去除字符串首尾空白开启) */ defaultRequest: true, defaultResponse: { codeField: 'resultCode', dataField: 'data', successCode: 'SUCCESS', isThrowWhenFail: true, }, authenticate: (instance) => ({ isAuthenticateFailed: (error) => { const errorCode = error.response?.data?.errorCode; return error.response?.status === 401 || (errorCode ? AUTH_ERROR_CODES.includes(errorCode) : false); }, doReAuthenticate: async (_error: AxiosError>) => { window.location.href = '/login'; }, enableRefreshToken: true, doRefreshToken: async () => { const res = await instance.post('/refresh-token', { refreshToken: localStorage.getItem('refresh_token'), }); const { token, refreshToken } = res.data; localStorage.setItem('access_token', token); localStorage.setItem('refresh_token', refreshToken); }, }), errorMessage: { handler: (errorResponse: AxiosResponse>, networkErrMsg) => { if (!errorResponse.config || !errorResponse.data) { return; } if (errorResponse.config.errorMessageMode === 'none') { return; } const errorMessage = errorResponse.data?.errorCodeDes || networkErrMsg || errorResponse.data?.errorCode || '未知错误'; if (errorResponse.config.errorMessageMode === 'message') { ElMessage({ message: errorMessage, type: 'error', plain: true, grouping: true, }); } else if (errorResponse.config.errorMessageMode === 'modal') { ElMessageBox({ title: '错误提示', message: errorMessage, type: 'error', showCancelButton: false, confirmButtonText: '知道了', }).catch(() => {}); } }, defaultLanguage: 'zh', }, setup: (client) => { // 这里可以继续挂载第三方插件,例如 axios-retry // axiosRetry(client, { retries: 3 }); client.interceptors.request.use((config) => { const token = localStorage.getItem('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); }, }); // 可选:设置全局错误提示语言 // setGlobalLanguage('en'); ``` -------------------------------- ### createParamsSerializerInterceptor Source: https://context7.com/greatauk/axios-easy/llms.txt Installs a qs-based paramsSerializer on the axios instance for fine-grained control over how array parameters are serialized in query strings. The global format can be overridden on a per-request basis. ```APIDOC ## `createParamsSerializerInterceptor` — Query string serialization Installs a `qs`-based `paramsSerializer` on the axios instance for fine-grained control over how array parameters are serialized in query strings. The global format is set at install time; individual requests can override it via `qsStringifyArrayFormat` in the request config. ```ts import axios from 'axios'; import { createParamsSerializerInterceptor } from 'axios-easy/params-serializer-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com' }); const interceptorId = createParamsSerializerInterceptor(instance, { qsStringifyArrayFormat: 'brackets', // global default }); // Uses global 'brackets' format → ?tags[]=frontend&tags[]=backend instance.get('/posts', { params: { tags: ['frontend', 'backend'], page: 1 } }); // Per-request override → ?categories=tech,news instance.get('/articles', { params: { categories: ['tech', 'news'] }, qsStringifyArrayFormat: 'comma', }); // Format comparison for { items: ['a', 'b', 'c'] }: // 'brackets' → items[]=a&items[]=b&items[]=c // 'indices' → items[0]=a&items[1]=b&items[2]=c // 'repeat' → items=a&items=b&items=c // 'comma' → items=a,b,c instance.interceptors.request.eject(interceptorId); ``` ``` -------------------------------- ### Integration with UI Frameworks Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Shows examples of integrating the error message interceptor with popular UI frameworks like Element Plus and Ant Design. ```APIDOC ## Integration with UI Frameworks ```typescript // Element Plus Integration import { ElMessage } from 'element-plus'; const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { ElMessage.error(errorMessage); }, defaultLanguage: 'zh' } ); // Ant Design Integration import { message } from 'antd'; const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { message.error(errorMessage); }, defaultLanguage: 'en' } ); ``` ``` -------------------------------- ### Configuring openapi-ts-request Source: https://github.com/greatauk/axios-easy/blob/main/openapi-ts-request.md Set up the `openapi-ts-request.config.ts` file to define API modules, specify schema paths, import statements for custom request functions, and configure hooks. This example shows configurations for 'system' and 'auth' API groups. ```typescript import { defineConfig } from 'openapi-ts-request'; export default defineConfig([ { describe: '系统模块 API', requestImportStatement: `import { request } from '@/utils/request'; import type { AxiosRequestConfig } from 'axios'; `, requestOptionsType: 'AxiosRequestConfig', schemaPath: 'http://domain/v2/api-docs?group=system', serversPath: './api/system', // apiPrefix: "'/todo'", // priorityRule: 'include', // 模式规则,可选include/exclude/both // includeTags: [], // 根据指定的 tags 生成代码, priorityRule=include则必填 // excludeTags: [], // 根据指定的 tags 不生成代码 // includePaths: [], // 根据指定的 paths 生成代码 // excludePaths: [], // 根据指定的 paths 不生成代码 hook: { afterOpenApiDataInited: patchApiJSON, }, }, { describe: '认证 API', requestImportStatement: `import { request } from '@/utils/request'; import type { AxiosRequestConfig } from 'axios'; `, requestOptionsType: 'AxiosRequestConfig', schemaPath: 'http://domain/v2/api-docs?group=auth', serversPath: './api/auth', // apiPrefix: "'/todo'", // priorityRule: 'include', // 模式规则,可选include/exclude/both // includeTags: [], // 根据指定的 tags 生成代码, priorityRule=include则必填 // excludeTags: [], // 根据指定的 tags 不生成代码 // includePaths: [], // 根据指定的 paths 生成代码 // excludePaths: [], // 根据指定的 paths 不生成代码 hook: { afterOpenApiDataInited: patchApiJSON, }, }, ]); ``` -------------------------------- ### Create Params Serializer Interceptor Source: https://github.com/greatauk/axios-easy/blob/main/README.md Installs an interceptor to serialize request parameters, using 'qs' for `application/x-www-form-urlencoded` format. Configure global array format or override per request. Use `qsStringifyArrayFormat` on `AxiosRequestConfig`. ```typescript import { createParamsSerializerInterceptor } from 'axios-easy/params-serializer-interceptor'; // 1. Install the interceptor and set global configuration const interceptorId = createParamsSerializerInterceptor(axiosInstance, { qsStringifyArrayFormat: 'brackets' // Globally use brackets format by default }); // 2. Normal request - use global configuration axiosInstance.get('/api/users', { params: { tags: ['frontend', 'backend'], // Serialized to: tags[]=frontend&tags[]=backend active: true, page: 1 } }); // 3. Request-level configuration - override global configuration // qsStringifyArrayFormat is now a valid property of AxiosRequestConfig axiosInstance.get('/api/search', { params: { categories: ['tech', 'news'] }, qsStringifyArrayFormat: 'comma' // Use comma-separated format for this request: categories=tech,news }); // 5. Use qs default format (indices) when no configuration is passed createParamsSerializerInterceptor(axiosInstance); // Uses indices format // 6. Remove the interceptor axiosInstance.interceptors.request.eject(interceptorId); ``` -------------------------------- ### Get Filename from Content-Disposition Header Source: https://github.com/greatauk/axios-easy/blob/main/README.md Safely parses filenames from the `content-disposition` header, supporting both `filename*` (RFC-5987) and `filename=` formats, including special characters and quoted filenames. ```typescript import { getFilenameFromContentDisposition } from 'axios-easy/utils'; const fileName = getFilenameFromContentDisposition(response.headers['content-disposition']); const header1 = "attachment; filename*=UTF-8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.zip"; // Contains Chinese "test file.zip" const header2 = 'attachment; filename="a simple file.txt"'; const header3 = 'inline; filename=another-file.pdf'; const header4 = 'form-data; name="file"; filename="report with spaces.docx"'; const header5 = 'attachment; filename="semicolon;.txt"'; // Quoted filename containing a semicolon console.log(`Header 1: ${getFilenameFromContentDisposition(header1)}`); // Output: Header 1: 测试文件.zip console.log(`Header 2: ${getFilenameFromContentDisposition(header2)}`); // Output: Header 2: a simple file.txt console.log(`Header 3: ${getFilenameFromContentDisposition(header3)}`); // Output: Header 3: another-file.pdf console.log(`Header 4: ${getFilenameFromContentDisposition(header4)}`); // Output: Header 4: report with spaces.docx console.log(`Header 5: ${getFilenameFromContentDisposition(header5)}`); // Output: Header 5: semicolon;.txt ``` -------------------------------- ### Running the openapi command Source: https://github.com/greatauk/axios-easy/blob/main/openapi-ts-request.md Execute the `openapi` script defined in `package.json` to generate API client code based on the configuration. ```bash pnpm openapi ``` -------------------------------- ### Demonstrate Language Priority Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Illustrates the priority order for language selection: request config, global setting, and interceptor default. ```typescript // 示例:演示语言优先级 setGlobalLanguage('zh'); // 全局设置为中文 const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { console.error(errorMessage); }, defaultLanguage: 'en' } ); try { // 这个请求将使用中文错误信息,优先于拦截器默认语言和全局语言 const response = await axiosInstance.get('/api/data', { errorMessageLanguage: 'zh' }); } catch (error) { // 错误信息将显示中文 } ``` -------------------------------- ### Basic Usage Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Demonstrates how to create and use the error message interceptor with a default language setting. ```APIDOC ## Basic Usage ```typescript import axios from 'axios'; import { createErrorMessageInterceptor } from 'axios-easy'; const axiosInstance = axios.create(); // Create error message interceptor (default Chinese) const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { console.error('Error message:', errorMessage); // Here you can call your UI components to display errors, e.g.: // message.error(errorMessage); // Element Plus // notification.error({ message: errorMessage }); // Ant Design } } ); ``` ``` -------------------------------- ### Registering the openapi command in package.json Source: https://github.com/greatauk/axios-easy/blob/main/openapi-ts-request.md Add a script to your `package.json` to easily run the `openapi-ts` command. ```json { "scripts": { "openapi": "openapi-ts" } } ``` -------------------------------- ### Initialize App with Language and Interceptor Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Set the global language and create the error message interceptor during application initialization. Ensure the language is saved and retrieved from local storage. ```typescript function initializeApp() { const savedLanguage = localStorage.getItem('language') || 'zh'; setGlobalLanguage(savedLanguage as 'zh' | 'en'); // 创建 axios 拦截器 createErrorMessageInterceptor(axiosInstance, { handler: handleError }); } ``` -------------------------------- ### Making Requests with Configured Axios Instance Source: https://github.com/greatauk/axios-easy/blob/main/README.md After configuring the `axiosInstance` using `createRequestClient`, you can use it to make HTTP requests. The `request` function is a shorthand for `axiosInstance` with default configurations applied. ```typescript // 现在,你可以使用配置好的 axiosInstance 发起请求了 async function getUserInfo() { try { const userInfo = await axiosInstance.get>('/user/info', { errorMessageMode: 'modal', }); console.log(userInfo); // { id: 1, name: 'Alice' } } catch (error) { console.error('获取用户信息失败'); } } async function getPetInfo() { const petInfo = await request('/api/pet/1', { errorMessageMode: 'modal', }); console.log(petInfo); // { id: 1, name: 'Alice' } } ``` -------------------------------- ### Modular Axios Instance Configuration Source: https://github.com/greatauk/axios-easy/blob/main/TRAINING.md Create a base Axios instance and progressively add custom and library interceptors. This approach is suitable for complex projects requiring high customization or integration with other Axios modules. ```typescript // src/utils/request.ts import axios from 'axios'; import { createDefaultRequestInterceptor } from 'axios-easy/default-request-interceptor'; import { createDefaultResponseInterceptor } from 'axios-easy/default-response-interceptor'; import { createAuthenticateInterceptor } from 'axios-easy/authenticate-interceptor'; import { createErrorMessageInterceptor } from 'axios-easy/error-message-interceptor'; // ... 其他导入 // 1. 创建原生 Axios 实例 const axiosInstance = axios.create({ baseURL: '/api', timeout: 30 * 1000, }); // 2. 添加业务 Token 拦截器 (这是你自己的业务逻辑) axiosInstance.interceptors.request.use((config) => { const token = localStorage.getItem('access_token'); if (token && config.headers) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 3. 按需应用 axios-easy 的拦截器 createDefaultRequestInterceptor(axiosInstance, { /* ...配置... */ }); createDefaultResponseInterceptor(axiosInstance, { /* ...配置... */ }); createAuthenticateInterceptor(axiosInstance, { /* ...配置... */ }); createErrorMessageInterceptor(axiosInstance, { /* ...配置... */ }); // 4. 如果需要, 还可以集成第三方库 // import axiosRetry from 'axios-retry'; // axiosRetry(axiosInstance, { retries: 3 }); export default axiosInstance; ``` -------------------------------- ### Importing openapi-ts-request utilities Source: https://github.com/greatauk/axios-easy/blob/main/openapi-ts-request.md Import necessary utility functions from `axios-easy/openapi-ts-request-util`. ```typescript import { patchApiJSON, toUpperFirstLetter } from 'axios-easy/openapi-ts-request-util'; ``` -------------------------------- ### Manual Interceptor Combination with axios-easy Source: https://github.com/greatauk/axios-easy/blob/main/skills/use-axios-easy/SKILL.md Recommended for fine-grained control over each interceptor. Import necessary interceptors and apply them to an axios instance. The order of interceptor application is important. ```typescript import axios from 'axios'; import { createDefaultRequestInterceptor } from 'axios-easy/default-request-interceptor'; import { createDefaultResponseInterceptor } from 'axios-easy/default-response-interceptor'; import { createAuthenticateInterceptor } from 'axios-easy/authenticate-interceptor'; import { createErrorMessageInterceptor } from 'axios-easy/error-message-interceptor'; const axiosInstance = axios.create({ baseURL: 'https://api.example.com', responseReturn: 'body', // 扩展属性:控制响应返回格式 errorMessageMode: 'message', // 扩展属性:控制错误提示方式 timeout: 30000, }); // 按需添加拦截器(顺序很重要) createDefaultRequestInterceptor(axiosInstance, { ... }); createDefaultResponseInterceptor(axiosInstance, { ... }); createAuthenticateInterceptor(axiosInstance, { ... }); createErrorMessageInterceptor(axiosInstance, { ... }); ``` -------------------------------- ### API Reference: createErrorMessageInterceptor Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Provides the signature and parameter details for the `createErrorMessageInterceptor` function. ```APIDOC ## API Reference ### createErrorMessageInterceptor ```typescript function createErrorMessageInterceptor( axiosInstance: AxiosInstance, options:{ handler: HandleErrorMessage, defaultLanguage?: SupportedLanguage } ): number ``` **Parameters**: - `axiosInstance`: Axios instance - `options`: Configuration options **Returns**: - `number`: Interceptor ID, used for removing the interceptor ``` -------------------------------- ### `patchApiJSON` Source: https://context7.com/greatauk/axios-easy/llms.txt A utility for normalizing OpenAPI JSON tag names to English camelCase using their `description` field, intended for codegen pipelines. ```APIDOC ## `patchApiJSON` — OpenAPI JSON tag normalizer A utility for use with [openapi-ts-request](https://github.com/openapi-ui/openapi-ts-request) that rewrites OpenAPI JSON tag names to English camelCase using their `description` field. Intended for codegen pipelines where Chinese tag names in a Swagger spec need to be normalized before generating TypeScript client code. ### Parameters - **openApiSpec** (object): The OpenAPI specification object. ### Returns - **object**: The modified OpenAPI specification object with normalized tag names. ``` -------------------------------- ### Language Priority Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Details the priority order for language selection: request configuration, global setting, and interceptor default. ```APIDOC ## Language Priority The language selection follows this priority (from highest to lowest): 1. **Request Configuration Language** - `errorMessageLanguage` in a single request 2. **Global Language Setting** - Global language set via `setGlobalLanguage()` 3. **Interceptor Default Language** - Default language specified when creating the interceptor ```typescript // Example: Demonstrating language priority setGlobalLanguage('zh'); // Global setting to Chinese const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { console.error(errorMessage); }, defaultLanguage: 'en' } ); try { // This request will use Chinese error messages, taking precedence over the interceptor's default and global language. const response = await axiosInstance.get('/api/data', { errorMessageLanguage: 'zh' }); } catch (error) { // Error messages will be displayed in Chinese } ``` ``` -------------------------------- ### createAuthenticateInterceptor Source: https://context7.com/greatauk/axios-easy/llms.txt Attaches a response interceptor to handle authentication failures (e.g., 401) and implement transparent token refresh with request queuing. ```APIDOC ## `createAuthenticateInterceptor` — Auth failure & token refresh Attaches a response interceptor that handles authentication failures (default: HTTP 401) and, when `enableRefreshToken: true`, implements transparent token refresh with request queuing — all concurrent requests issued while a refresh is in progress are held in a queue and replayed automatically with the new token after a successful refresh. ```ts import axios from 'axios'; import { createAuthenticateInterceptor } from 'axios-easy/authenticate-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com' }); const interceptorId = createAuthenticateInterceptor(instance, { // Custom predicate; defaults to response?.status === 401 isAuthenticateFailed: (error) => { const code = error.response?.data?.errorCode; return error.response?.status === 401 || code === 'TOKEN_TIMEOUT'; }, // Called when auth cannot be recovered (redirect to login) doReAuthenticate: async (error) => { console.warn('Session expired, redirecting to login.', error.response?.data); window.location.href = '/login'; }, enableRefreshToken: true, // requires doRefreshToken when true doRefreshToken: async () => { // Throw here to trigger doReAuthenticate const { data } = await axios.post('https://api.example.com/auth/refresh', { refreshToken: localStorage.getItem('refresh_token'), }); localStorage.setItem('access_token', data.token); localStorage.setItem('refresh_token', data.refreshToken); }, }); // Remove when no longer needed instance.interceptors.response.eject(interceptorId); ``` ``` -------------------------------- ### Global Language Setting Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Explains how to set the global language for error messages and how the interceptor automatically uses this setting. ```APIDOC ## Global Language Setting (Recommended) ```typescript import { setGlobalLanguage, getGlobalLanguage } from 'axios-easy'; // Set global language to English setGlobalLanguage('en'); // When creating the interceptor, no language needs to be specified; it will automatically use the global setting. const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { console.error('Error:', errorMessage); } } ); // Dynamically switch language setGlobalLanguage('zh'); // Switch to Chinese console.log(getGlobalLanguage()); // Output: 'zh' ``` ``` -------------------------------- ### Responsive Language Switching in React Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Implement a custom React hook to manage and switch the application's language. This hook handles state updates, global language settings, and local storage persistence. ```typescript function useLanguage() { const [language, setLanguage] = useState<'zh' | 'en'>(() => getGlobalLanguage()); const switchLanguage = (newLanguage: 'zh' | 'en') => { setGlobalLanguage(newLanguage); setLanguage(newLanguage); localStorage.setItem('language', newLanguage); }; return { language, switchLanguage }; } ``` -------------------------------- ### Single Request Language Setting Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Illustrates how to specify the language for error messages on a per-request basis. ```APIDOC ## Set Language for a Single Request ```typescript // Global default is Chinese, but a specific request uses English try { const response = await axiosInstance.get('/api/users', { errorMessageLanguage: 'en' // This request uses English error messages }); } catch (error) { // Error messages will be displayed in English } ``` ``` -------------------------------- ### Interceptor Level Default Language Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Shows how to set a default language for a specific interceptor, which takes precedence over the global setting. ```APIDOC ## Set Default Language at Interceptor Level ```typescript // Set default to English (takes precedence over global language setting) const interceptorId = createErrorMessageInterceptor( axiosInstance, { handler: (error, errorMessage) => { console.error('Error:', errorMessage); }, defaultLanguage: 'en' }, ); ``` ``` -------------------------------- ### Defining a generic request function Source: https://github.com/greatauk/axios-easy/blob/main/openapi-ts-request.md Create a generic `request` function that uses an `axiosInstance` (wrapped by `easy-axios`) to handle API calls. This function is intended for use with `openapi-ts-request`. ```typescript // utils/request.ts // axiosInstance 是经过 easy-axios 包装的 axios 实例 /** * 通用的请求方法 */ export async function request(url: string, config: AxiosRequestConfig) { try { const res = await axiosInstance({ ...config, url, }); return res as T; } catch (error: any) { throw error.response ? error.response.data : error; } } ``` -------------------------------- ### API Reference: SupportedLanguage Type Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Defines the `SupportedLanguage` type, outlining the available language options. ```APIDOC ### SupportedLanguage ```typescript type SupportedLanguage = 'zh' | 'en'; ``` Supported language types: - `'zh'`: Chinese - `'en'`: English ``` -------------------------------- ### createDefaultRequestInterceptor Source: https://context7.com/greatauk/axios-easy/llms.txt Attaches a request interceptor that normalizes request payloads and extends timeouts for file downloads. Behaviors are configurable globally or per-request. ```APIDOC ## `createDefaultRequestInterceptor` — Request normalization Attaches a request interceptor that (1) automatically extends the timeout for file-download requests (`responseType: 'blob' | 'arraybuffer'`) and (2) normalizes request payloads (`data` and `params`) by trimming strings, dropping `undefined` keys, and converting empty strings to `null`. Both behaviors are configurable globally and can be overridden per-request via `normalizePayload` in the request config. ```ts import axios from 'axios'; import { createDefaultRequestInterceptor } from 'axios-easy/default-request-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com', timeout: 10_000 }); const interceptorId = createDefaultRequestInterceptor(instance, { // true → multiply base timeout by 10 for blob/arraybuffer requests // false → disable timeout extension // fn → custom timeout calculation extendTimeoutWhenDownload: (defaultTimeout, config) => defaultTimeout * 5, normalizePayload: { trim: true, // ' Alice ' → 'Alice' dropUndefined: true, // { name: 'Alice', age: undefined } → { name: 'Alice' } emptyStringToNull: true, // { email: '' } → { email: null } }, }); // Per-request override: disable normalization for this call instance.post('/upload', formData, { normalizePayload: { trim: false, dropUndefined: false, emptyStringToNull: false }, }); // Remove interceptor when no longer needed instance.interceptors.request.eject(interceptorId); ``` ``` -------------------------------- ### Create Authenticate Interceptor Source: https://context7.com/greatauk/axios-easy/llms.txt Attaches a response interceptor to handle authentication failures (e.g., 401) and implement token refresh. Configure custom predicates for failure detection, actions for re-authentication, and enable transparent token refresh with request queuing. ```typescript import axios from 'axios'; import { createAuthenticateInterceptor } from 'axios-easy/authenticate-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com' }); const interceptorId = createAuthenticateInterceptor(instance, { // Custom predicate; defaults to response?.status === 401 isAuthenticateFailed: (error) => { const code = error.response?.data?.errorCode; return error.response?.status === 401 || code === 'TOKEN_TIMEOUT'; }, // Called when auth cannot be recovered (redirect to login) doReAuthenticate: async (error) => { console.warn('Session expired, redirecting to login.', error.response?.data); window.location.href = '/login'; }, enableRefreshToken: true, // requires doRefreshToken when true doRefreshToken: async () => { // Throw here to trigger doReAuthenticate const { data } = await axios.post('https://api.example.com/auth/refresh', { refreshToken: localStorage.getItem('refresh_token'), }); localStorage.setItem('access_token', data.token); localStorage.setItem('refresh_token', data.refreshToken); }, }); // Remove when no longer needed instance.interceptors.response.eject(interceptorId); ``` -------------------------------- ### API Reference: getGlobalLanguage Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Provides information on the `getGlobalLanguage` function for retrieving the current global language setting. ```APIDOC ### getGlobalLanguage ```typescript function getGlobalLanguage(): SupportedLanguage ``` Gets the current global language setting. **Returns**: - `SupportedLanguage`: The current global language ``` -------------------------------- ### processFileStream(response, options) Source: https://github.com/greatauk/axios-easy/blob/main/README.md Handles file download streams, intelligently distinguishing between file streams and error JSON responses. It uses `file-saver` for downloading and can extract error messages from JSON. ```APIDOC ## processFileStream(response, options) ### Description Core function for processing file download streams. It intelligently determines if the response is a file stream or JSON containing error information. If successful (file stream), it extracts the filename from the `content-disposition` header and uses `file-saver`'s `saveAs` to trigger a browser download. If it's an error (JSON), it parses and returns the error message. ### Configuration Options (`ProcessFileStreamOptions`) ```ts export type ProcessFileStreamOptions = { /** * Custom filename. If provided, this will be used preferentially over parsing from the `content-disposition` header. */ fileName?: string; /** * Field name to extract the error text from when the response body is JSON error information. * @default 'errorCodeDes' */ errorMessageField?: string; }; ``` ### Usage ```ts import { processFileStream } from 'axios-easy/utils'; async function handleExport() { try { const response = await axiosInstance.get('/api/export-file', { responseType: 'blob', // Must specify response type responseReturn: 'raw', // Requires raw response to get headers }); const errMsg = await processFileStream(response, { errorMessageField: 'errorCodeDes' }); if (errMsg) { // ElMessage.error(errMsg); console.error(errMsg); } else { // ElMessage.success('Export successful'); console.log('Export successful'); } } catch (error) { // Handle network or other errors } } ``` ``` -------------------------------- ### `processFileStream` Source: https://context7.com/greatauk/axios-easy/llms.txt Handles ambiguous responses from file-export endpoints. It triggers a browser download for blobs or parses and returns error messages for JSON responses. ```APIDOC ## `processFileStream` — File download handler Handles the ambiguous response from file-export endpoints: if the backend returns a blob, it triggers a browser download using `file-saver`; if the backend returns `application/json` (indicating a business error), it parses and returns the error message. Use with `responseReturn: 'raw'` and `responseType: 'blob'`. ### Parameters - **response** (AxiosResponse): The raw Axios response object, expected to be of type 'blob'. - **options** (object, optional): Configuration options. - **fileName** (string, optional): Overrides the filename from the `content-disposition` header. - **errorMessageField** (string, optional): The field in the JSON error response that contains the error message. Defaults to 'errorCodeDes'. ### Returns - **Promise** A promise that resolves to the error message string if an error occurred, or null if the file was downloaded successfully. ``` -------------------------------- ### Create Default Request Interceptor Source: https://context7.com/greatauk/axios-easy/llms.txt Attaches a request interceptor to normalize payloads and extend timeouts for file downloads. Configure global settings or override per-request. Use `normalizePayload` to trim strings, drop undefined keys, and convert empty strings to null. Use `extendTimeoutWhenDownload` to adjust timeouts for 'blob' or 'arraybuffer' response types. ```typescript import axios from 'axios'; import { createDefaultRequestInterceptor } from 'axios-easy/default-request-interceptor'; const instance = axios.create({ baseURL: 'https://api.example.com', timeout: 10_000 }); const interceptorId = createDefaultRequestInterceptor(instance, { // true → multiply base timeout by 10 for blob/arraybuffer requests // false → disable timeout extension // fn → custom timeout calculation extendTimeoutWhenDownload: (defaultTimeout, config) => defaultTimeout * 5, normalizePayload: { trim: true, // ' Alice ' → 'Alice' dropUndefined: true, // { name: 'Alice', age: undefined } → { name: 'Alice' } emptyStringToNull: true, // { email: '' } → { email: null } }, }); // Per-request override: disable normalization for this call instance.post('/upload', formData, { normalizePayload: { trim: false, dropUndefined: false, emptyStringToNull: false }, }); // Remove interceptor when no longer needed instance.interceptors.request.eject(interceptorId); ``` -------------------------------- ### `saveAs` Source: https://context7.com/greatauk/axios-easy/llms.txt Re-exports the `saveAs` function from `file-saver` for triggering browser downloads of Blob objects or URLs with enhanced cross-browser compatibility. ```APIDOC ## `saveAs` — Re-exported file-saver Re-exports `saveAs` from [`file-saver`](https://github.com/eligrey/FileSaver.js) for triggering browser downloads from `Blob` objects or URLs, with better cross-browser compatibility than the `` approach. ### Parameters - **data** (Blob | string | HTMLCanvasElement): The data to save. Can be a Blob object, a URL string, or a canvas element. - **filename** (string): The name of the file to save. - **options** (object, optional): Additional options for saving, passed directly to the underlying `file-saver` library. ``` -------------------------------- ### getFilenameFromContentDisposition Source: https://github.com/greatauk/axios-easy/blob/main/README.md Safely parses filenames from the `content-disposition` response header, supporting both `filename*` (RFC-5987) and `filename=` formats. ```APIDOC ## getFilenameFromContentDisposition ### Description Safely parses the filename from the `content-disposition` response header. It supports both `filename*` (RFC-5987) and `filename=` formats, ensuring correct handling of various encoding and quoting scenarios. ### Usage ```ts import { getFilenameFromContentDisposition } from 'axios-easy/utils'; const fileName = getFilenameFromContentDisposition(response.headers['content-disposition']); const header1 = "attachment; filename*=UTF-8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.zip"; // Contains Chinese "测试文件.zip" const header2 = 'attachment; filename="a simple file.txt"'; const header3 = 'inline; filename=another-file.pdf'; const header4 = 'form-data; name="file"; filename="report with spaces.docx"'; const header5 = 'attachment; filename="semicolon;.txt"'; // Quoted filename containing a semicolon console.log(`Header 1: ${getFilenameFromContentDisposition(header1)}`); // Output: Header 1: 测试文件.zip console.log(`Header 2: ${getFilenameFromContentDisposition(header2)}`); // Output: Header 2: a simple file.txt console.log(`Header 3: ${getFilenameFromContentDisposition(header3)}`); // Output: Header 3: another-file.pdf console.log(`Header 4: ${getFilenameFromContentDisposition(header4)}`); // Output: Header 4: report with spaces.docx console.log(`Header 5: ${getFilenameFromContentDisposition(header5)}`); // Output: Header 5: semicolon;.txt ``` ``` -------------------------------- ### API Reference: setGlobalLanguage Source: https://github.com/greatauk/axios-easy/blob/main/src/error-message-interceptor/README.md Details the `setGlobalLanguage` function for setting the global default language. ```APIDOC ### setGlobalLanguage ```typescript function setGlobalLanguage(language: SupportedLanguage): void ``` Sets the global default language. **Parameters**: - `language`: The language to set ('zh' | 'en') ``` -------------------------------- ### Extended AxiosRequestConfig Properties Source: https://context7.com/greatauk/axios-easy/llms.txt These properties extend the standard AxiosRequestConfig and can be configured globally or per-request to customize behavior. ```APIDOC ## Extended `AxiosRequestConfig` Properties `axios-easy` extends `AxiosRequestConfig` via TypeScript module augmentation. These properties can be set on the axios `defaults`, per-request config, or in `axios.create()`: | Property | Type | Default | Description | |---|---|---|---| | `responseReturn` | `'raw' \| 'body' \| 'data'` | `'body'` | Controls what the response interceptor returns | | `errorMessageMode` | `'message' \| 'modal' \| 'none'` | `'message'` | How errors are presented to the user | | `errorMessageLanguage` | `'zh' \| 'en'` | global / `'zh'` | Per-request error message language | | `normalizePayload` | `{ trim?, dropUndefined?, emptyStringToNull? }` | — | Per-request payload normalization (overrides global) | | `qsStringifyArrayFormat` | `'brackets' \| 'indices' \| 'repeat' \| 'comma'` | `'indices'` | Per-request array serialization format | | `__retry__` | `boolean` | — | Internal flag to prevent auth refresh infinite loops — do not set manually | ```