# easy-api

简易的api请求封装，基于`fetch`

附带接口集合生成器(gen-api)

## 安装

`npm i -S @iscdev/easy-api`

## 使用

```typescript
import {callApi} from '@iscdev/easy-api'

callApi('https://xxx.com/aaa/bbb', {...options})
```

## api

### `callApi` 调用api接口

> 定义：`function callApi(url: string, options?: CallApiOptions)`

#### 参数

* `url`: `string`，待请求的链接，相对路径和绝对路径皆可
* `options?`: `CallApiOptions`，配置

#### `CallApiOptions` 配置属性

* `method?`: `'GET' | 'POST' | 'DELETE' | 'PUT'`，请求方法, 默认：'GET'
* `headers?`: 键值对，头信息
* `params?`: 任何，数据
* `requestContentType?`: `'form-data' | 'form-urlencoded' | 'json' | 'raw' | 'binary'`，请求体类型，默认：'json'
* `plugins?`: `Plugin[]`，插件集合
* `parseResponseFunc?`: `ResponseParseFunc`，响应体解析方法，默认为`code/data`的风格

#### 返回值

`Promise<any>`

默认情况下，如果请求成功则返回`data`字段，如果失败或者网络异常则抛出异常，具体看`parseResponseFunc`配置的解析风格

## `pollingApi` 轮询api接口

> 定义：`pollingApi<T>(callApiFunc: () => Promise<T>, options?: PollingApiOptions<T>): () => void`

#### 参数

* `callApiFunc`: `() => Promise<T>`，一个callApi的请求
* `options?`: `PollingApiOptions<T>`，配置

#### `PollingApiOptions` 配置属性

* `interval?`: `number`，间隔，默认：1000ms
* `times?`: `number`，次数，小于0表示无限轮询，大于0表示有限次数轮询，等于0表示不请求也不轮询，默认：-1
* `onResponse?`: `(data: T) => boolean | void`，消息回调方法，如果方法返回true则终止轮询
* `onError?`: `(error: Error | CodeError) => boolean | void`，错误回调方法，如果方法返回true则继续轮询，优先级高于interruptWhenError
* `interruptWhenError?`: `boolean`，当发生错误时终止轮训，默认：true

#### 返回值

返回一个方法，调用即可终止轮询

## 插件

支持插件系统

内置了一个插件：`apiLogger`，用于在控制台打印接口调用日志

也可以自己开发插件，只要实现如下接口即可：

```typescript
interface Plugin {
    /*请求初始化*/
    init?: (context: FetchContext) => boolean | void
    /*请求前*/
    beforeCall?: (context: FetchContext) => boolean | void
    /*遇到网络错误*/
    onCatchNetError?: (context: FetchContext) => boolean | void
    /*请求后*/
    afterCall?: (context: FetchContext) => boolean | void
    /*遇到接口错误*/
    onCatchError?: (context: FetchContext) => boolean | void
}
```

### 使用

插件的使用分为全局设置和单次设置

#### 全局设置

`callApi.plugins = [apiLogger({ beauty: true })];`  
只要在设置`callApi.plugins`即可直接修改全局的插件列表，此后的所有请求都会应用这些插件

#### 单次设置

`callApi('https://xxx.com/aaa/bbb', {plugins:[apiLogger({ beauty: true })]})`  
这样设置的插件仅对该次请求有效

> 注意：单次设置的插件先于全局设置的插件

## 接口集合生成器cli

`call-api`只是暴露出来的较为低级的api，实际开发中会将其进行二次封装。本库提供了`buildApiCollection`方法，来生成接口集合

### 接口集合构造器

定义：`function buildApiCollection<T>(apiConfigs:any, apis?:any): Proxy<T>`

#### 参数

* `apiConfigs`:`键值对`，接口配置，会通过生成器生成的
* `apis?`:`object`，传入原始的api集合对象

#### 返回值

`Proxy<T>`
返回一个代理对象即为接口集合实例，泛型是调用时传入的，泛型类型也是生成器生成的，可以直接在对象上点出接口分组和接口名(
如果调用时传入泛型T的话)

### 接口集合实例说明

* 为了能通过字面量来编写调用代码，所以分组名和接口名都会转换成驼峰式的
* 如果同一个接口链接通过`method`来区分功能的，则会直接使用形如`.get, .post, .delete`的方法名来补全
* 如果链接完整，也会使用`method`来做为方法名的前缀，如：`getStatusList, postSaveByProductKey`

返回值为`Promise<xxx>`，其中xxx为传入的泛型类型

### cli使用

只要安装了`@isc-dev/easy-api`就可以使用该cli，也可以全局安装
> 目前仅支持swagger的文档转换

#### 参数

* -i --input <string>       文档接口地址或者导出的json文档
* -o --output <string>      输出目录, 如: "src/api" (默认: ".")
* -r --root-path <string>   接口url的根路径, 如: "/api/bios/ibms-basic" (默认: "")
* -n --namespace <string>   命名空间, 如: "basic" (默认: "")
* -h --headers <string...>  头部信息，一般用于鉴权 , 如: "Cookie:abc=123"

例子：  
`gen-api -o src/api -n basic -r /api/bios/ibms-basic -i 'http://10.30.30.87:38080/api/bios/ibms-basic/v3/api-docs' -h 'Cookie: X-Isyscore-Permission-Sid=1e4617a5-394c-44ba-be7a-fbde72cfce08'`  
或使用本地swagger导出的json文件  
`gen-api -o src/api -n basic -r /api/bios/ibms-basic -i '/aaa/bbb.json'`

如果生成成功，则会在输出目录写入两个文件，这两个文件需配合使用

1. [命名空间]-types.d.ts 接口定义文件
2. [命名空间]-configs.json 接口配置文件

命名空间即为命令行执行是传入的`-n`参数，下面以`basic`举例

然后就可以暴露出接口集合实例了：

```typescript
import basicConfig from './basic-configs.json';
import {basic} from '@/api/basic-types';

export const basicApi = buildApiCollection<basic.IApis>(basicConfig);
```

随后即可使用，且有智能提示  
![img.png](assets/idea.png)

## 新版生成器 gen-api-v2 🆕

为了解决原版生成器在复杂项目中的稳定性问题，我们开发了全新的 `gen-api-v2`，具有以下优势：

### ✨ 主要改进

- **🔧 完整 OpenAPI 支持**: 全面支持 OpenAPI 3.x 和 Swagger 2.x 标准
- **🛡️ 更强稳定性**: 重新设计的架构，单个接口解析失败不影响整体生成
- **🎯 精确类型系统**: 支持联合类型、枚举、泛型等复杂 TypeScript 类型
- **⚡ 性能优化**: 智能缓存和并行处理，生成速度更快
- **🔍 详细错误信息**: 精确定位问题所在，便于调试
- **🔌 完全兼容**: 与原版生成器完全兼容，可无缝迁移

### 🚀 快速开始

```bash
# 使用新版生成器
gen-api-v2 -i "https://api.example.com/swagger.json" -o "src/api" -n "myApi"

# 所有原版参数都兼容
gen-api-v2 -o src/api -n basic -r /api/v1 -i 'https://api.example.com/docs' -h 'Authorization: Bearer token'
```

### 📖 详细文档

完整的使用文档请查看：[Generator v2 使用文档](docs/generator-v2.md)

### 🔄 迁移指南

从原版生成器迁移非常简单：

```bash
# 原版命令
gen-api -i "doc-url" -o "output" -n "namespace"

# 新版命令（直接替换）
gen-api-v2 -i "doc-url" -o "output" -n "namespace"
```

生成的文件格式完全兼容，无需修改现有代码！

### 🆚 版本对比

| 特性 | gen-api (原版) | gen-api-v2 (新版) |
|------|-------------|----------------|
| OpenAPI 3.x | 部分支持 | ✅ 完整支持 |
| Swagger 2.x | ✅ 支持 | ✅ 支持 |
| 类型系统 | 基础 | ✅ 增强 |
| 错误处理 | 基础 | ✅ 完善 |
| 稳定性 | 一般 | ✅ 优秀 |
| 性能 | 一般 | ✅ 优化 |

推荐在新项目中使用 `gen-api-v2`，现有项目可以逐步迁移。
