前言
在我们日常开发的过程中,后端同学一般会提供Swagger UI 用于帮助前端发开同学查看接口文档编写,在最开始开始写前端项目的过程中(古老项目中),会在项目里面新建用于存放接口的文件,但是前后端文档的编写和维护会花费很大的成本。随着后面对于ts的使用 ,对应的service、interface等ts声明代码。如果后端接口都遵循RESTful 风格,那么我们可以通过一些工具或者自动化脚本,以提高开发者效率和 减少重复的工作。
利用pont自动化生成接口文档
Pont 把 swagger、rap、dip 等多种接口文档平台,转换成 Pont 元数据。Pont 利用接口元数据,可以高度定制化生成前端接口层代码,接口 mock 平台和接口测试平台。
其中 swagger 数据源,Pont 已经完美支持。并在一些大型项目中使用了近两年,各种高度定制化需求都可以满足。
详情查看:developer.aliyun.com/article/787…
快速开始
- 1、在 vscode 中安装 vscode 插件 pont 以获取 pont 的全部能力。插件使用方法请参考:vscode-pont
- 2、添加 pont-config.json
pont 一旦检测到有效的 pont-config.json 文件即可启动。pont 支持 pont start 命令快速生成 pont-config.json 配置文件。
全局安装 pont-engine
// npm
npm i -g pont-engine
// 或yarn
yarn global add pont-engine
在你的项目中运行 pont start 命令,按照提示输入配置完成接入。
Tips:
- 确保服务端使用 Swagger(目前只支持 Swagger V1、V2、V3),提供的数据源接口是免登录的。如果不是,请后端帮忙简单配置一下,或者使用 fetchMethodPath 配置,通过自定义 fetch 方法获取带鉴权的接口的文档。
- 若需替换默认的请求信息,请参阅pontCore。
配置pont-config.json
- originUrl: 接口平台提供数据源的 open api url(需要免登),目前只支持 Swagger。如 "petstore.swagger.io/v2/swagger.…"
- outDir: 生成代码的存放路径,使用相对路径即可。如:"./src/api"
- templatePath: 指定自定义代码生成器的路径(使用相对路径指定)。一旦指定,pont 将即刻生成一份默认的自定义代码生成器。自定义代码生成器是一份 ts 文件,通过覆盖默认的代码生成器,来自定义生成代码。默认的代码生成器包含两个类,一个负责管理目录结构,一个负责管理目录结构每个文件如何生成代码。自定义代码生成器通过继承这两个类(类型完美,可以查看提示和含义),覆盖对应的代码来达到自定义的目的。具体使用方法请参看自定义代码生成器文档。
- prettierConfig: 生成的代码会用 prettier 来美化。此处配置 prettier 的配置项即可,具体可以参考 prettier 文档。
- usingMultipleOrigins: pont 支持一个项目中配置多个 Swagger 来源。此处配置是否启用多数据源
- origins: 配置每个数据来源
- mocks:
-
- 子字段:
-
-
- 字段名:"enable" 类型:boolean 默认值: true 含义:是否生效
- 字段名:"basePath" 类型:string 默认值:"" 含义:接口的 basePath
- 字段名: "port" 类型:string 默认值:8080 含义:mocks 服务的端口号
- 字段名 "wrapper" 类型:string 默认值:"{"code": 0, "data": {response}, "message": ""}" 含义:接口返回结构,pont 可以计算返回数据类型(比如此处会替换到 {response}),此处可以指定接口返回结构。
-
- 等等..
例子:
{
"usingMultipleOrigins": true,
"origins": [
{
"name": "xxx1",
"originUrl": "http://xxx1/api-docs"
},
{
"name": "xxx2",
"originUrl": "http://xxx2/api-docs"
}
],
"outDir": "./client/pont",
"prettierConfig": {
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
},
"mocks": {
"enable": true,
"port": 8081
},
"templatePath": "./client/pontTemplate"
}
一旦检测到项目中存在有效的 pont-config.json 配置文件,插件便会启动。你将在插件底部看到如下状态栏:
- sync:重新请求远程接口数据,重新计算本地接口数据和远程接口数据在接口模块和接口返回对象(基类)上的差异。
- all:将本地所有接口模块、接口返回对象与远程已更新数据保持一致。
- mod:选择并同步本地接口模块,与远程接口数据保持一致。
配置pontTemplate
import { CodeGenerator, Interface } from 'pont-engine'
export default class MyGenerator extends CodeGenerator {
/** 获取接口内容的类型定义代码 */
getInterfaceContentInDeclaration(inter: Interface): string {
const paramsCode = inter.getParamsCode()
const bodyParamsCode = inter.getBodyParamsCode()
const isGetRequest = inter.method.toLocaleLowerCase() === 'get'
const requestParams = isGetRequest
? `params: Params`
: `params: ${bodyParamsCode}`
return `
export ${paramsCode}
export type Response = ${inter.responseType};
export const init: Response;
export function request(${requestParams}): Promise<${inter.responseType}>;
`
}
/**
* 获取所有模块的 index 入口文件 目前对应pont-engine的包以及插件 v1.5.2版本
*/
getModsIndex() {
let conclusion = `
export {
${this.dataSource.mods.map(mod => mod.name).join(', \n')}
};
`
// dataSource name means multiple dataSource
if (this.dataSource.name) {
conclusion = `
export const ${this.dataSource.name} = {
${this.dataSource.mods.map(mod => mod.name).join(', \n')}
};
`
}
return `
${this.dataSource.mods
.map(mod => {
return `import * as ${mod.name} from './${mod.name}';`
})
.join('\n')}
${conclusion}
`
}
/** 获取接口实现内容的代码 */
getInterfaceContent(inter: Interface): string {
// 根据内部使用习惯修改
// 目前只存在 query 或 data 的传参方式,不存在两者并存的情况
const { path } = inter
// 增加 auth 服务调用逻辑
const paramsCode = inter.getParamsCode()
const isGetRequest = inter.method.toLocaleLowerCase() === 'get'
const requestParamName = isGetRequest ? 'params' : 'data'
const requestParams = isGetRequest ? `params: Params` : `data: Params`
return `
/**
* @desc ${inter.description}
*/
import * as defs from '../../baseClass';
import axios from '@/services/request';
export ${paramsCode}
export const init = ${inter.response.getInitialValue()};
export async function request(${requestParams}): Promise<any> {
return axios({
url: '${inter.getDsName()}${path}',
${requestParamName},
method: '${inter.method}',
});
}
`
}
}
生成的接口文件
使用
引入使用
import { uploadImage } from '@pont/promote/common/uploadImage'
uploadImage(formData).then((res) => {
console.log(res)
})
挂载全局使用
在pont/index.ts文件中
import { defs as xxxDefs, xxx } from './xxx'
import { defs as promoteDefs, promote } from './promote'
;(window as any).defs = {
xxx: xxxDefs,
promote: promoteDefs,
}
;(window as any).API = {
xxx,
promote,
}
在代码中使用
const data = await API.promote.common.uploadImage.request(formData)
注:pont-engine v1.5.2版本的index.ts生成需要通过 getModsIndex来帮助生成