你还在自己写接口或者接口类型吗?

前言

作为前端开发,我们在开发中,能不能不再关注接口层面的东西,比如:编写接口函数,接口的参数处理(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 版本

开始

  1. 安装依赖:pnpm i @api-helper/cli

  2. 安装完成之后,使用指令生成配置文件 npx apih init

  3. 编辑生成的配置文件,填写接口文档地址。

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: '',
    },
  ],
});
  1. 最后使用指令生成即可: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脚本文件即可。

手动启动步骤

  1. 打包浏览器代码,进入web包下,输入命令:pnpm run build
  2. 打包服务器端代码,进入server包下,输入命令:pnpm run build
  3. 启动服务,进入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服务中有一个文件模块生成的功能,它可以绑定模版与接口关联,然后生成整个模块的代码文件,创建文件的过程也可以省略了。

相关推荐
刺客-Andy5 分钟前
React 第十九节 useLayoutEffect 用途使用技巧注意事项详解
前端·javascript·react.js·typescript·前端框架
谢道韫6669 分钟前
今日总结 2024-12-27
开发语言·前端·javascript
嘤嘤怪呆呆狗20 分钟前
【插件】vscode Todo Tree 简介和使用方法
前端·ide·vue.js·vscode·编辑器
ᥬ 小月亮33 分钟前
Js前端模块化规范及其产品
开发语言·前端·javascript
码小瑞1 小时前
某些iphone手机录音获取流stream延迟问题 以及 录音一次第二次不录音问题
前端·javascript·vue.js
weixin_1891 小时前
‌Vite和Webpack区别 及 优劣势
前端·webpack·vue·vite
半吊子伯爵1 小时前
开发过程优化·自定义鼠标右键菜单
前端·javascript·自定义鼠标右键菜单
xcLeigh1 小时前
HTML5实现好看的喜庆圣诞节网站源码
前端·html·html5
Tirzano1 小时前
vue3 ts 简单动态表单 和表格
前端·javascript·vue.js
杰~JIE1 小时前
前端工程化概述(初版)
前端·自动化·工程化·前端工程化·sop