npm package: @huaiyou/api-client
Description: Unified API client with axios and TypeScript
Latest version: 1.0.0

# @huaiyou/api-client

> 基于 Axios 的企业级网络请求库，专为 Monorepo 架构设计。采用分层架构与插件化设计，提供高可扩展性、强类型支持和多场景预设实例。

## 🌟 核心特性

- **分层架构设计**：配置层、插件层、核心层、工具层、业务实例层解耦。
- **插件化机制**：功能完全解耦，支持按需插拔（重试、缓存、取消重复请求、Mock、日志）。
- **多场景预设**：内置后台管理（Admin）、前台应用（Web）、第三方集成（ThirdParty）三种标准实例。
- **TypeScript 强类型**：提供完整的类型定义，支持泛型推导，确保开发体验与代码安全。
- **灵活配置**：支持“全局配置 > 实例配置 > 请求配置”三级覆盖策略。
- **统一错误处理**：标准化的错误格式与处理流程。

---

## 📦 安装

```bash
# 在 Monorepo 根目录
pnpm add @huaiyou/api-client --filter <your-package-name>
```

---

## 🚀 快速上手

### 1. 使用预设实例

项目内置了三种常用的预设实例，开箱即用：

```typescript
import { adminClient, webClient, thirdPartyClient } from '@huaiyou/api-client';

// 后台管理场景（自动重试、强错误提示）
const getUserList = () => {
  return adminClient.get('/users', {
    params: { page: 1 },
  });
};

// 前台 C 端场景（GET 请求自动缓存、性能优先）
const getNews = () => {
  return webClient.get('/news/latest');
};

// 第三方接口（无默认插件干扰）
const getGithubStars = () => {
  return thirdPartyClient.get('https://api.github.com/repos/vuejs/core');
};
```

### 2. 请求级别配置（覆盖）

你可以在发起请求时，临时修改插件行为：

```typescript
// 强制开启重试，即使是 webClient
webClient.get('/important-data', {
  retry: {
    retries: 3,
    retryDelay: 1000,
  },
});

// 禁用缓存，强制获取最新数据
webClient.get('/news/latest', {
  cache: {
    enable: false,
  },
});

// 开启 Mock 数据（开发调试用）
adminClient.get('/users/1', {
  mock: {
    enable: true,
    data: { id: 1, name: 'Mock User' },
    delay: 500,
  },
});
```

---

## 🧩 插件系统详解

`api-client` 的核心能力通过插件实现，所有插件均支持在创建实例时配置，或在请求时动态覆盖。

### 1. 取消重复请求 (CancelRequestPlugin)

防止短时间内发送相同的请求（如用户频繁点击按钮）。

- **默认行为**：当通过相同的 URL 和参数发起新请求时，自动取消上一个未完成的请求。
- **配置参数**：
  ```typescript
  {
    requestKey?: string; // 手动指定请求唯一标识
  }
  ```

### 2. 请求重试 (RetryPlugin)

网络不稳定或服务器临时错误时自动重试。

- **默认行为**：Admin 实例默认开启，Web 实例默认关闭。
- **配置参数**：
  ```typescript
  {
    retries?: number;      // 重试次数，默认 3
    retryDelay?: number;   // 重试间隔(ms)，默认 1000
    shouldRetry?: (error: any) => boolean; // 自定义重试条件
  }
  ```

### 3. 请求缓存 (RequestCachePlugin)

缓存 GET 请求的响应结果，减少网络请求。

- **默认行为**：Web 实例默认开启（5分钟 TTL），Admin 实例默认关闭。
- **配置参数**：
  ```typescript
  {
    enable?: boolean;  // 是否开启
    ttl?: number;      // 缓存时间(ms)，默认 5 * 60 * 1000
    storage?: Storage; // 存储介质，默认 localStorage
  }
  ```

### 4. Mock 数据 (MockRequestPlugin)

拦截请求并返回模拟数据，无需后端接口。

- **默认行为**：默认关闭。
- **配置参数**：
  ```typescript
  {
    enable?: boolean; // 是否开启
    data?: any;       // Mock 数据内容
    delay?: number;   // 模拟延迟(ms)，默认 200
  }
  ```

### 5. 请求日志 (RequestLoggerPlugin)

在控制台输出详细的请求和响应日志。

- **默认行为**：仅在开发环境 (`development`) 开启。

### 6. 无感 Token 刷新 (TokenRefreshPlugin)

当接口返回 401 时，自动挂起并发请求，刷新 Token 后重试。

- **默认行为**：默认不开启，需要传入刷新逻辑。
- **配置参数**：
  ```typescript
  {
    refreshToken: () => Promise<void>; // 刷新 Token 的具体实现
    shouldRefresh?: (error: AxiosError) => boolean; // 自定义触发条件，默认 status === 401
  }
  ```

### 7. 请求 ID (RequestIdPlugin)

自动为每个请求生成 UUID 并添加到 Header 中，方便全链路追踪。

- **配置参数**：
  ```typescript
  {
    headerName?: string; // Header 键名，默认 'X-Request-ID'
  }
  ```

---

## 🛠️ 创建自定义实例

如果内置实例无法满足需求，你可以使用 `createAxios` 工厂函数创建完全自定义的实例。

```typescript
import { createAxios, CancelRequestPlugin, RetryPlugin } from '@huaiyou/api-client';

const myClient = createAxios({
  // Axios 基础配置
  baseURL: 'https://api.myservice.com',
  timeout: 10000,
  headers: { 'X-App-Version': '1.0.0' },

  // 插件列表（按需加载）
  plugins: [new CancelRequestPlugin(), new RetryPlugin()],

  // 拦截器
  interceptors: {
    request: (config) => {
      // 自定义 Token 逻辑
      config.headers['Authorization'] = 'Bearer my-token';
      return config;
    },
    response: (res) => {
      return res.data; // 直接返回 data 字段
    },
    error: (error) => {
      // 自定义错误上报
      reportError(error);
      return Promise.reject(error);
    },
  },
});
```

---

## 🏗️ 架构设计图

```mermaid
graph TD
    A[业务代码] --> B(Api Client Instances)
    B --> C{Core Layer}
    C --> D[Interceptors]
    C --> E[Plugins]

    subgraph Plugins [插件层]
        E1[CancelRequest]
        E2[Retry]
        E3[Cache]
        E4[Mock]
        E5[Logger]
    end

    subgraph Core [核心层]
        C1[createAxios Factory]
        C2[Axios Instance]
    end

    subgraph Instances [预设实例]
        I1[Admin Client]
        I2[Web Client]
        I3[ThirdParty Client]
    end
```

## 📝 最佳实践

1.  **优先使用预设实例**：90% 的场景下，`adminClient` 和 `webClient` 已经足够使用。
2.  **按需覆盖配置**：不要为了一个特殊请求去修改全局配置，使用请求级别的 `config` 覆盖即可。
3.  **类型安全**：始终利用 TypeScript 的泛型来定义响应数据结构。
    ```typescript
    interface User {
      id: number;
      name: string;
    }
    // response 类型自动推导为 User
    const user = await adminClient.get<User>('/users/1');
    ```
4.  **环境隔离**：利用 `env.ts` 中的配置，确保开发、测试、生产环境自动切换 `baseURL`。

## 🤝 贡献指南

1.  **新增插件**：在 `src/plugins` 目录下实现 `ApiPlugin` 接口。
2.  **修改配置**：在 `src/config` 目录下调整默认值。
3.  **提交代码**：请遵循项目的 Commit Lint 规范。