背景
前端项目使用的ts,但在对接后端生成的yapi文档时,只提供了数据结构,需要自己手动根据结构填写ts类型,接口目录中存在几十甚至上百个接口,手动填写会存在非常多无意义的机械运动。
yapi文档是后端同学部署,不方便直接去操作yapi项目,所以决定写一个无侵入式的接口生成脚手架工具。
于是花了几个小时的时间,结合自己的项目,完成了初版脚手架工具yapi-cli
,在实现的这个过程中熟悉脚手架开发的流程,并且发布自己的npm
包。
接下来会介绍脚手架的使用和开发的过程。
介绍与使用
脚手架功能很简单,就两个功能,一个初始化配置,一个创建。
安装
推荐全局安装
sh
npm i -g yapi-ts-cli
查看帮助
执行yt -h
就可以查看帮助信息。
shell
yapi脚手架工具,帮助通过yapi创建ts和api文件
Options:
-V, --version output the version number
-h, --help display help for command
Commands:
init 初始化配置
create [options] 创建ts文件
help [command] display help for command
yt create
相关命令可以一键创建全部的类型接口,也可以指定创建接口文件。
运行yt create -h
可以查看create
相关的帮助信息
shell
创建ts文件
Options:
-all, --all 下载该项目下所有接口
-id, --id <id> 下载指定id接口
-h, --help display help for command
使用
首先初始化配置执行
shell
yt init
修改配置信息
js
{
path: "/src/api", // 保存目录
cookie: "", // yapi的cookie
url: "", // 项目地址 例如:http://117.xx.xx.xx:3000
projectId: "", // 项目的id,例如:http://117.xx.xx.xx:3000/project/11/interface/api/43,这里的11就是项目id,填写11
// headers: (info) => {}, // 特殊修改头部字符
// apiContent: (info) => {}, // 修改底部api接口字符
}
统一创建ts文件执行
shell
yt create -all
只创建单个文件执行
shell
yt create -id <id>
执行下载的得到的ts文件举例
ts
import { post } from "@/utils/request";
export interface HardwareRebindCollectorReqQueryTypes {
[k: string]: unknown;
}
export interface HardwareRebindCollectorReqTypes {
/**
* 设备型号
*/
device_model?: string;
/**
* 设备地址 true
*/
mac_arr?: string;
/**
* 设备所属网关ID
* 如果设备是网关
*/
wan_id?: string;
[k: string]: unknown;
}
export interface HardwareRebindCollectorResTypes {
/**
* 信道
*/
channel?: string;
/**
* 设备id
*/
device_id?: string;
/**
* 网关ID
*/
wan_id?: string;
/**
* 网关Lora地址
*/
wan_lora_addr?: string;
[k: string]: unknown;
}
/**
* 标题: 绑定采集器设备
* 描述: 绑定采集器设备
* 地址:http://11.xxx.xx.xxx:3000/project/11/interface/api/155
*/
export const hardwareRebindCollector = (data?: HardwareRebindCollectorReqTypes) =>
post<HardwareRebindCollectorResTypes>("/api/hardware/rebind_collector", data);
脚手架开发
库介绍
功能相对比较简单,不是很复杂,脚手架所使用的常用库,这里先介绍一下几个库的作用
js
"commander": "^11.0.0",
"json-schema-to-typescript": "^13.1.1"
commander
提供了一种简洁且强大的方式来处理命令行参数、选项、子命令和帮助文档。使得创建复杂的 CLI 工具变得更加简单,能够轻松的实现脚手架中的命令行交互,在这个脚手架开发中,我仅使用了两个交互命令,create
和init
,在代码中是这样的:
js
program
.name("yapi-cli")
.description("yapi脚手架工具,帮助通过yapi创建ts和api文件")
.version(packageJson.version);
// 配置初始化
program.command("init").description("初始化配置").action(init);
// 文件创建
program
.command("create")
.description("创建ts文件")
.option("-all, --all", "下载该项目下所有接口")
.option("-id, --id <id>", "下载指定id接口")
.action(create);
program.parse();
通过commander
的program
方法,创建了两个简单的交互命令,command
定义命令名,description
进行描述,option
定义选项和选项的值,随后就是去实现init
和create
方法,当用户执行此子命令时,将调用 action
中的函数。
json-schema-to-typescript
要解决的核心问题是如何将yapi中的内容转换成ts文件,而yapi
所存储实际上是一个JsonSchema
数据,我们需要把一段json
转换成ts
类型,使用这个json-schema-to-typescript
转换库,能够很方便的转换成ts
类型,不用自己造轮子了。
让我们来看看yapi
中的JsonSchema
是什么样子的
json
{
"type": "object",
"properties": {
"device_model": {
"description": "设备型号",
"type": "string"
},
"mac_arr": {
"description": "设备地址 true",
"type": "string"
},
"version": {
"description": "设备版本",
"type": "string"
},
"wan_id": {
"description": "设备所属网关ID\n如果设备是网关",
"type": "string",
"example": "0"
}
},
"$$ref": "#/definitions/vo.RebindCollectorReq"
}
而通过json-schema-to-typescript
转换后得到ts
数据,是不是很方便。
ts
export interface HardwareRebindCollectorReqTypes {
/**
* 设备型号
*/
device_model?: string;
/**
* 设备地址 true
*/
mac_arr?: string;
/**
* 设备版本
*/
version?: string;
/**
* 设备所属网关ID
* 如果设备是网关
*/
wan_id?: string;
[k: string]: unknown;
}
init初始化实现
初始化只是将内置的配置文件copy了一份到执行目录,使用了fs-extra
库中的copySync
方法。
js
copySync(configPath, cwd + "/yapi-cli-config.mjs");
create实现
在create
中存在下载全部和下载单个ts文件,下载全部文件时,会调用yapi的接口获取接口列表,并遍历接口去挨个下载。
请求接口使用了axios
库,调用非常方便,携带cookie
直接请求完事
js
await axios.get(url, { headers: headers });
拿到了接口的信息后,调用json-schema-to-typescript
转换,并且拼接了头部请求,和尾部api内容,完成了一个完整的api请求文件。
最后保存到对应的目录中。
npm包发布
在package.json
中填写包信息
配置包名、版本、描述等信息
填写bin
入口文件,表示命令yt
会执行./bin/index.js
入口文件,而这个文件中编写的是前面commander
所编写的命令行交互。
js
"bin": {
"yt": "./bin/index.js"
},
使用npm link
可以连接开发中的包,能够直接全局使用。
使用npm login
登陆npm
账号
使用npm publish
发布npm
包,值得注意的是发布的时候容易重名,导致无法发布,可以先查询是否存在同名包后再发布。
总结
开发过程中也有遇到一些问题,例如一开始使用commonjs
的语法编写js,但后面发现很多库不支持,又切换到了es module
。配置文件本来使用json
直接存储,但是发现需要扩展的话使用json不方便,例如自定义头部尾部内容,一些地方的回调,生命周期配置,使用js能够直接编写函数插入到代码当中。
开发时间比较短,代码可能还存在一些问题,没有仔细考虑,但目前能够满足自身需求。
通过这次脚手架开发,感受到效率的提升,熟练掌握后,能够在工作中发挥更大的作用。