介绍一个工具,通过swagger得到ts所需要的出入参定义,并生成可直接调用的函数(请求层解决方案)

2,444 阅读5分钟

一、前言

  1. 开始写swagger2ts这个包,纯粹只是不想写后端返回的数据的出参定义和注释(interface.d.ts文件)
  2. 使用的同事希望通过接口地址能找到这个定义,于是加了paths文件(path.ts)。
  3. 第二版中台的同学想把它做成满足公司的请求层解决方案,其实就是生成可以直接调用的函数(function.ts) 视频链接

二、分析

其实我们再用swagger上联调接口(其他工具也类似),你会发现接口的出参,有类型,有注释(如下)。那它这里的数据是怎么得到的呢,打开控制台,network找到/xx/api-docs, 返回definitions、paths等字段。

  • definitions,是生成interface.d.ts的数据依赖
  • paths, 是生成paths.d.ts文件和function.ts文件的数据依赖

三、行动起来

四、插件功能

根据使用者的配置会在配置路径下生成以下

├── swagger2ts
	├── [serviceName1]
 		├── interface.d.ts
 		├── paths.d.ts
		└── function.ts
	├── [serviceName2]
		├── interface.d.ts
		├── paths.d.ts
		└── function.ts
        ├── [...]
        ├── request.ts
	└── transation.json 

1. service-xxx/interface.d.ts文件作用

当前服务下所有的DTO的ts定义和tsdoc注释(如下)

/**
 * @param answerContent (string) 回答内容
 * @param answerPersonId (string) 回答人id
 * @param subjectInfoDTO (SubjectInfoDTO) 受试者信息
 */ 
export interface AnswerDTO {
    answerContent: string | null;
    answerPersonId: string | null;
    subjectInfoDTO: SubjectInfoDTO;
}

2. service-xxx/paths.d.ts文件作用

当前服务所有接口地址,及对应的请求方式和出入参类型(来自interface.d.ts)。 找到接口方便通过f12(ctrl+单击)跳转到定义

import { AnswerDTO } from './interface.d';
interface pathsObj {
    "/calendar/aaa": {
        method: "post";
        parameters:{
            query:any;
        },
        data: Array<AnswerDTO>;
    };
}

3. service-xxx/function.ts文件作用

接收一个axios实例或者其他基于promise封装的http库。给每个接口生成唯一的函数,函数已知接口地址,请求方式,出入参类型。

/**
 * 备注:获取访视预约提醒列表
 */
export const getSubjectVisitAppointNoticeListUsingPOST = function(this: any,params: {
        query: {isAppointed: number;};
        body: Partial<SubjectVisitAppointDTO>;}): Promise<PageInfo_SubjectVisitOutputDTO> {
    return this.__http.post('/service-xxx' + url, body) as any;
};

interface-paths.png

4. translation.json 文件作用

保存上次翻译的结果,第三方翻译字符总数的限制。

5. request.ts 文件作用

最后用户直接使用的文件,输出一个API函数,包含所有服务的调用接口函数

request.png

配置及使用 (三选一即可)

参数

NameTypeDefaultDescription
*serverList{Array<{serviceName: string;serviceUrl:string;}或string>}[]必传 如果穿数组字符串 ['sms-service'] 后端服务名,如果是字符串对象,必传服务名称和服务地址
*appUrl{String}"http://eureka.dev.com:1111/eureka/apps"必传 后端所有服务注册信息
*outputPath{String}{path.resolve(__dirname, "./src/swagger2ts")}生成文件输出路径
fanyi{object}{baidu: { appid: "xxx",secretKey: "xxxx",maxLimit: 2000}}配置百度翻译 appid和秘钥,maxLimit 不能超过2000

1、webpack插件使用

webpack.config.js

const Swapper2TsPlugin = require("swagger-ts-plugin");
/**
 * outputPath 输出地址
 * appUrl 必须是公司的eureka所有服务列表地址 http://eureka.dev.com:1111 + /eureka/apps 
 * 当前地址返回的是xml格式数据,插件会处理
 */
// 原本想解析项目中的所有文件夹,自动的检查出服务名称,服务地址,实际做的时候发现不是很好做
// 所有它实际上不算一个webpack插件,
module.exports = {
    plugins: [
        new Swapper2TsPlugin({
            outputPath: path.resolve(__dirname, "../"),
            // v1.1.11 以后支持这种混合类型
            serverList: [
                "trialpartner-web",
                "sms-service",
                {
                    serviceName: "xxx-service",
                    serviceUrl: "http://172.12.12.111:8001/",
                },
            ],
            // 如果serverList中只提供服务名称,则必须提供 http://eureka.dev.com:1111(eureka地址)+ /eureka/apps
            appUrl: "http://eureka.dev.com:1111/eureka/apps",
        }),
    ],
};

2、作为工具使用(偷懒没做cli ^o^)

// 因为swagger-ts-plugin插件也直接暴露出build方法,开发者可以直接调用
// npm scripts 增加一条命名,"build:ts":"node xxx.js";

// 创建一个xxx.js;
new Swapper2TsPlugin({
    /* 配置,如上 */
}).build();

// 执行 yarn build:ts就能run起来了

3、vscode插件(目前还是版本1,后面陆续升级)

  1. vscode插件市场找到 vscode-swagger2ts-plugin 安装

  2. 配置,请打开 文件-> 首选项 -> 设置, 找到swagger-ts-plugin;

// vscode插件是每项单独配置,这里的配置等同于serverList
"swagger-ts-plugin.serviceList": [
    {
        "serviceName": "xxx-service",
        "serviceUrl": "http://172.20.37.153:8000/",
    },
    "sms-service"
]
  1. 使用 ctrl+shift+p 打开Command Palette,输入 swagger2ts 回车。

  2. 请注意如果是新开的vscode窗口未选择文件是不会有任何文件生成。如果你的配置没有问题,当前窗口也选择了文件项目。你将在文件根目录得到一个swagger2ts文件夹,包含多个子文件夹数量等于配置的服务数量。

  3. vscode插件额外给根目录的.gitignore文件添加忽略/swagger2ts的配置。

生成的数据如何使用

视频链接

// test.ts 这里的地址根据生成的swagger2ts文件
import request from "xxx/swagger2ts/request.ts";
import axios from "axios";

let http = tmsRequest.create({
    timeout: 500000,
    baseURL: "/api/",
});

const API = request(http);
// 走网关 请求
API["服务名称"]["后端接口地址"]("参数").then((val) => {});

// 例
const msg = API.smsService["/homeMenu/getHomeMenuList"]({
    body: {
        projectId: "xxx",
        siteId: "xxx",
        subjectInfoId: "xxx",
    },
}).then((val) => {});

已完成功能

  • 输入定义部分interface.d.ts。
  • 接口对应的出入参,请求方式等paths.d.ts。
  • 生成可直接调用的函数 function.ts。
  • 最后导出API函数 request.ts。
  • 定义名称包含中文部分,使用翻译转成英文。
  • 兼容swagger3.0(还不完善)。
  • 根据required字段,给定义添加字段是否可选

后续需要完善的内容

  • 插件单元测试
  • auto mock
  • vscode插件升级到2.0。
  • serviceList中服务名称目前区分大小写,后面忽略大小写
  • 返回的函数catch部分还没完善
  • 配置controller,只输出自己想要的函数。
  • 完成 未使用函数tree shaking

最后

第一次写文章,有很多不足的地方,有任何建议可以找我邮箱1543259203@qq.com

如果觉得还好的话,给个⭐️⭐️ 谢谢啦~ swagger-ts-plugin

vscode-swagger2ts-plugin