为了提效,手写脚手架根据yapi生成ts接口文件

背景

前端项目使用的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 工具变得更加简单,能够轻松的实现脚手架中的命令行交互,在这个脚手架开发中,我仅使用了两个交互命令,createinit,在代码中是这样的:

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();

通过commanderprogram方法,创建了两个简单的交互命令,command定义命令名,description进行描述,option定义选项和选项的值,随后就是去实现initcreate方法,当用户执行此子命令时,将调用 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能够直接编写函数插入到代码当中。

开发时间比较短,代码可能还存在一些问题,没有仔细考虑,但目前能够满足自身需求。

通过这次脚手架开发,感受到效率的提升,熟练掌握后,能够在工作中发挥更大的作用。

相关推荐
前端老宋Running7 分钟前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔7 分钟前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654269 分钟前
Android的自定义View
前端
WILLF10 分钟前
HTML iframe 标签
前端·javascript
枫,为落叶27 分钟前
Axios使用教程(一)
前端
小章鱼学前端32 分钟前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah33 分钟前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝35 分钟前
手搓一个简简单单进度条
前端
uup39 分钟前
JavaScript 中 this 指向问题
javascript
L***B5681 小时前
如何安装linux版本的node.js
linux·运维·node.js