前言
作为前端开发,我们在开发中,能不能不再关注接口层面的东西,比如:编写接口函数,接口的参数处理(queryString参数,路径参数,FormData参数),或者使用TS的时候还得接口类型。有没有一些工具或者能自动处理这些?
答案是肯定的,@api-helper/cli
来了。
为什么选择它?已经存在了其他工具,也能达到这些功能,比如:
- yapi-to-typescript
- swagger-typescript-api
- @umijs/openapi
经过测试,他们或多或少存在一些问题
比如:它们需要严格注释规范,例如dot字段解析,当后端定义一个字段:userInfo.name
在它们的解析规则里面这种是直接解析成"userInfo.name"
,整体作为一个字段,而@api-helper/cli会将userInfo
解析成一个对象,name
是它的属性,更符合参数定义,当然也支持Array类型。
在其他方面yapi-to-typescript 在openapi3.1版本中生成失败;@umijs/openapi 不兼容openapi2版本;swagger-typescript-api需要相对严格的格式,vo类不能出现非英文字符,否则会报错,接口如果存在使用query接受动态参数也会容易出错,前端解析后会出现$字符导致解析失败。
不可否认的是,他们也是有很多优点,比如@umijs/openapi可以根据分类生成单文件接口,@api-helper/cli 和 yapi-to-typescript 采用同样的策略,所有接口类型都在一个文件中,存在问题是单文件过大,但是现代构建工具,支持treeShaking功能,这种情况下,@api-helper/cli 能做分类生成单文件生成接口,但是没必要。
@api-helper/web 还提供了web页面,操作选择接口,字段,生成想要的代码,在web服务中,自定义模版,生成任何想要的代码。以及对请求参数的校验等功能、mock数据生成等等功能。
@api-helper/cli
- 内置解析:openapi(swagger)、yapi
- 支持openapi2.0、openapi3.0 以及最新的 openapi3.1 版本
开始
-
安装依赖:
pnpm i @api-helper/cli
-
安装完成之后,使用指令生成配置文件
npx apih init
-
编辑生成的配置文件,填写接口文档地址。
js
import { defineConfig } from '@api-helper/cli';
export default defineConfig({
// 输出文件路径,会根据后缀名(.js|.ts)判断是生成TS还是JS文件
outputFilePath: 'src/api/index.ts',
// 接口请求函数文件路径
requestFunctionFilePath: 'src/api/request.ts',
// 接口文档服务配置
documentServers: [
{
// 文档地址【当下面的type为swagger类型时,可以读取本地文件,这里就是一个本地文件路径】
url: 'http://接口文档地址',
// 文档类型,根据文档类型,调用内置的解析器,默认值: 'swagger'【内置yapi和swagger的解析,其他文档类型,添加parserPlugins自行实现文档解析】
type: 'swagger',
// 获取数据的key,body[dataKey]
dataKey: '',
},
],
});
- 最后使用指令生成即可:
npx apih
更多配置参考:官方文档
生成后代码
- src/api/index.ts
如果生成的代码是index.js,会自动增加一个文件名称相同,后缀名为.d.ts
的文件,该文件包含了接口的类型定义,写JS的也有类型提示。
请求调用中内置的 processRequestFunctionConfig
会自动处理queryParams参数,路径参数,FormData参数。
ts
/* tslint:disable */
/* eslint-disable */
/* prettier-ignore-start */
/* 代码生成时间: 2024-04-03 18:37:33 */
/* 提示:该文件由 API Helper CLI 自动生成,请勿直接修改。 */
/* 文档参考:https://github.com/ztz2/api-helper/blob/main/packages/cli/README.md */
// @ts-ignore
// prettier-ignore
import {
RequestFunctionRestArgsType,
processRequestFunctionConfig,
} from '@api-helper/cli/lib/helpers';
// @ts-ignore
// prettier-ignore
import request from './request';
// @ts-ignore
// prettier-ignore
type CurrentRequestFunctionRestArgsType = RequestFunctionRestArgsType<typeof request>;
/**
* @description 账户登录、账户登录【请求数据类型定义】
* @url [ POST ] /api/{nickName}/auth
*/
export interface ApiNickNameAuthRequestByPost {
// 图形验证码结果
code?: string;
// 密码密文(认证类型password必传)
password?: string;
// 手机号
phone: string;
// 授权范围,默认填all
scope?: string;
// 短信验证码结果
smsCode?: string;
// 登录机构ID
tenantId?: string;
// 账户名
username: string;
// 图形验证码key
uuid?: string;
}
/**
* @description 账户登录、账户登录【响应数据类型定义】
* @url [ POST ] /api/{nickName}/auth
*/
export interface ApiNickNameAuthResponseByPost {
// TokenResponseVO
// 授权令牌
accessToken: string;
// 当前登录机构ID
currentTenant: number;
// 账户昵称
nickName: string;
// 权限集合,登录成功返回
permissions: Array<string>;
// 登录确认令牌,若存在多机构不直接返回accessToken,通过SubmitToken确认登录机构
submitToken: string;
// 账户关联机构
tenants: Array<// TenantBO
{
id: number;
lastLoginTime: string;
tenantCode: string;
tenantName: string;
}>;
// 登录类型,1:账号密码,2:短信验证码
type: number;
// 账户ID
userId: number;
// 账户类型,0:管理用户,1:机构用户
userType: number;
// 账户名
username: string;
}
/**
* @description 账户登录、账户登录
* @url [ POST ] /api/{nickName}/auth
*/
export function apiNickNameAuthByPost(data: ApiNickNameAuthRequestByPost, extraData?: unknown, ...args: CurrentRequestFunctionRestArgsType) {
return request<ApiNickNameAuthResponseByPost>(
processRequestFunctionConfig(data, extraData, apiNickNameAuthByPost.requestConfig),
...args
);
}
apiNickNameAuthByPost.requestConfig = {
path: '/api/{username}/auth',
method: 'POST',
formDataKeyNameList: [],
pathParamKeyNameList: ['username'],
queryStringKeyNameList: [],
};
- src/api/request.ts 如果没有创建request.ts会自动创建
由于processRequestFunctionConfig
处理了请求参数,在request
函数中的config.path
也会有所变化,比如:如果存在queryParams参数(userID),路径参数等,此时config.path
将会变成/api/xxx/auth?userID=xxx
。而存在FormData参数时候,config.hasFormData
的值会为true,与之对于的config.data
会变成new FormData()
对象(兼容Nodejs,小程序或者不支持FormData实例的环境会忽略这个处理)。
这些前置性的处理,可以就让实现具体请求的时候,变得更加简单方便。
ts
import { RequestFunctionConfig } from '@api-helper/cli/lib/helpers';
// 自定义配置
export type RequestOptions = {};
export default async function request<ResponseData>(config: RequestFunctionConfig, options?: RequestOptions): Promise<ResponseData> {
return new Promise((resolve, reject) => {
// 以axios为例的请求配置
const requestConfig = {
url: config.path,
method: config.method,
data: config.data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
// 处理表单数据请求头
if (config.hasFormData) {
requestConfig.headers['Content-Type'] = 'multipart/form-data';
}
/**
* TODO待实现具体request请求逻辑...
* 基于axios实现具体请求的简单例子
axios(requestConfig).then((res) => {
resolve(res as unknown as ResponseData);
}).catch(reject);
*/
// 先用异步模拟request请求逻辑
setTimeout(() => {
resolve({} as unknown as ResponseData);
}, 1500);
});
}
调用接口
ts
import { apiNickNameAuthByPost } from '@/api';
apiNickNameAuthByPost({ username: 'xxx', phone: 'xxx' }).then((data) => {
console.log(data)
});
web服务
web服务提供了基于接口的自定义代码生成,使得代码生成更加具有灵活性,在介绍该功能之前,先简单说明API Helper的项目分包。@api-helper/cli 提供接口生成功能以及这里的web服务都是基于@api-helper/core和@api-helper/template实现。
- @api-helper/cli 该包提供了
apih
指令,用于接口生成。 - @api-helper/core 是解析接口文档的核心包。
- @api-helper/template 模版包,内置了class模版,ts类型模版,JS对象模版。
- @api-helper/web 该包提供web服务的前端操作页面。
- @api-helper/server 该包提供web服务的Server端。
启动web服务
- 下载整个仓库代码:
git clone https://github.com/ztz2/api-helper.git
- 如果是windows环境,并且安装了
pnpm
,鼠标双击项目run-web-server.bat
脚本文件即可。
手动启动步骤
- 打包浏览器代码,进入web包下,输入命令:
pnpm run build
。 - 打包服务器端代码,进入server包下,输入命令:
pnpm run build
。 - 启动服务,进入server包下,输入命令:
pnpm run start:prod
。- 服务启动后访问地址:http://localhost:3210。
- 如果需要更新最新代码运行,需要从步骤1开始,后续启动服务操作,都是步骤3。
启动成功后,代码该地址界面如下,点击添加,根据提示,填写接口文档地址。
接口请求参数校验功能
该功能用于校验请求参数是否缺少字段,必填项是否缺少值,支持queryParams参数和对象类型识别。在接口调试时,谷歌浏览器中,按下F12 -> network 找到对应的请求,复制该请求的paylod参数,直接丢进来即可检查是否缺少字段,结果一目了然,不能让锅留给前端一点点机会。
生成class、js对象
生成的代码,有对应的注释类型,字段label等。
生成表单模版等
mock数据生成
上面模版都是系统内置模版,自定义模版可以点击新增模版,或者编辑系统内置模版,参考内置模版语法,编写属于自己的的自定义模版。
web服务提供了基本的请求&响应参数对象展示,一定程度上可以代替接口文档。
最后
简单总结一下,接口层面的代码,直接交给@api-helper/cli
。web服务提供的功能,可以生成JS对象、JS类、mock数据以及表单模版代码。表单模版代码,在C端管理信息系统中,特别的好用,抽离出管理系统的表单代码,然后基于它自定义模版,每次生成的表单代码,接口字段都绑定好了,这不香?如果把模版功能运用熟悉了,可以把一个功能模块的(增删改查)都定义成模版,在web服务中有一个文件模块生成的功能,它可以绑定模版与接口关联,然后生成整个模块的代码文件,创建文件的过程也可以省略了。