npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@cxxgo/genapi

v1.0.21

Published

注:目前只支持解析 swagger 2.0 接口文档。

Downloads

24

Readme

api 自动生成工具

注:目前只支持解析 swagger 2.0 接口文档。

安装

npm install @cxxgo/genapi -D

使用

1. 生成配置文件

生成 apiConfig 配置文件:

genapi init

可选参数:

  • --force: 是否覆盖本地配置文件。

    配置文件支持 jsts 格式,如果本地已经存在apiConfig.tsapiConfig.js 配置文件,执行 genapi init --force 将会生成新的配置文件覆盖本地配置文件。

2. 生成 api

根据 apiConfig 中的配置自动生成 api:

genapi now

可选参数:

  • --config <configPath>: 自定义配置文件路径。

    执行 genapi now 时,默认将当前目录下的 apiConfig.tsapiConfig.js 当做配置文件。

    当然也可以手动指定,如:genapi now -c ./xxx/myApiConf.ts, 指定配置文件路径为 ./xxx/myApiConf.ts

  • --no-mock: 是否不生成 mock 数据。

    执行 genapi now 除了会生成 api 数据外,还会默认在 node_modules 目录下生成 mock 数据。 genapi now --no-mock 则不生成 mock 数据,可以一定程度上减少命令执行时间 。

3. 启动 mock 服务

启动本地 mock 服务,默认端口号 8090:

genapi mock-server

配置文件说明

1. apiList 配置选项:

| 配置项 | 是否必传 | 类型 | 默认值 | 说明 | | ----------- | -------- | ----------------------- | ------ | -------------------------------------------------------------------------- | | swaggerUrl | Y | String | / | 接口文档 json 数据地址(可以是服务端地址也可以是 swagger json 本地文件路径) | | outputDir | Y | String | / | 生成结果的输出目录 | | apiBody | Y | Function | / | 自定义 api 结构 | | pathRewrite | N | Function | / | 接口路径重写 | | apiName | N | Function | / | 自定义接口名称生成规则 | | fileName | N | String 或 Function | / | 自定义接口所属文件名称规则 | | gen | N | boolean | true | 是否生成 | | exclude | N | String 或 Regexp 或数组 | / | 无需生成的接口 | | include | N | String 或 Regexp 或数组 | / | 只需生成的接口(优先级比 exclude 低) | | httpTpl | N | String | / | 文件头部引入内容(通常用于引入封装的请求方法) | | fileExt | N | String | ts | 文件类型(可选值 ts 或 js) | | typeMap | N | Record<string, string> | / | 接口出入参类型映射 |

其中:

  • apiBody 自定义 api 结构

    配置示例:

    {
      apiList: [
        {
          /* 自定义 api 结构
           * @param url 接口路径(pathRewrite 后的路径)
           * @param originUrl 接口原始路径(接口文档上的路径)
           * @param method 请求方法(小写,如 get、post)
           * @param summary 服务端写的接口注释,可能为空字符串
           * @param name 接口名称(如果配了fileName 函数,那将是通过 fileName 函数处理后得到的名称,否则是工具使用默认规则生成的名称)
           * @param outputInterface 接口输出数据模型
           * @param parameters 接口所有入参
           * @param pstr1 由 parameters 处理得到,值如 data: { id: string },可能为空字符串
           * @param pstr2 由 parameters 处理得到,值如 data,可能为空字符串
           * @param pstr3 由 parameters 处理得到,当路径中存在参数时,会有值,值如 const { id } = data
           **/
          apiBody: ({ url, originUrl, method, summary, name, outputInterface, pstr1, pstr2, pstr3 }) => {
            const quotation = pstr3 ? '`' : "'" // 引号类型
            return `
              /** ${summary || '无注释'} */
              export function ${name}  (${pstr1}) :Promise<${outputInterface || undefined}>{
                ${pstr3 ? pstr3 : ''}
                return Http.${method}(${quotation}${url}${quotation}, ${pstr2})
              }`
          },
        },
      ]
    }

    以上配置将会生成如下 api 结构:

    /** 获取用户信息 */
    // 注:'data: { id: string }' 这一串即 apiBody 中的 pstr1
    export function userInfo(data: { id: string }): Promise<ExampleModel1> {
      const { id } = data // 注: 'const { id } = data' 这一串即 apiBody 中的 pstr3
      return request.get(`/api/user/info?${id}`)
    }
    
    /** 用户修改密码 */
    export function userChangePswd(data: ExampleModel2): Promise<ExampleModel3> {
      return request.post('/api/user/changePswd', data) // 注:'data' 即 apiBody 中的 pstr2
    }
  • pathRewrite 接口路径重写

    这个配置项用于接口路径重写。比较常见的使用场景是:接口文档上的路径(后面都称为‘原始路径’或‘接口原始路径’)是 /api/user/list, 但是实际访问路径需要添加前缀,如 /prefix/api/user/list

    配置示例:

    {
      apiList: [
        {
          pathRewrite: ({ url }) => {
            return `/prefix${url}`
          },
        },
      ]
    }
  • apiName 自定义接口名称生成规则

    默认的接口名称生成规则为: 去除原始路径开头可能存在的 /api后,将剩余的单词拼接起来。 如: 接口 /api/user/info/{id} 的默认名称为 userInfoId; 接口 /api/user/changePswd 的默认名称为 userChangePswd; 接口 /app-event-center/manageRuleConfig/list 的默认名称为 appeventcenterManageRuleConfigList

    特殊情况 1: 如果存在路径相同但方法不同的两个接口,如 : get: /api/user/infopost: /api/user/info,这两个接口的名称将分别被处理为 userInfoGetuserInfoPost

    特殊情况 2: 如果按照默认规则处理后的接口名称正好是 js 关键字,如delete, 则会在后面拼上 Fn,即默认处理后的接口名称为 deleteFn

    使用场景,有时候接口路径上统一带了很长的前缀,导致默认的接口名称特别长(如上面的 appeventcenterManageRuleConfigList),这种情况下就可以使用apiName自定义接口名称,使之更为美观些。

    配置示例:

    {
      apiList: [
        {
          /**
           * 自定义接口名称生成规则
           * @param url 接口路径(pathRewrite 后的路径)
           * @param originUrl 接口原始路径(接口文档上的路径)
           * @param method 请求方法(小写,如 get、post)
           * @param defaultApiName 默认的接口名称
           **/
          apiName: ({ url, originUrl, method, defaultApiName }) => {
            // appeventcenterManageRuleConfigList 处理为 manageRuleConfigList
            return defaultApiName.replace('appeventcenter', '').replace(/^\S/, (s) => s.toLowerCase())
          },
        },
      ]
    }
  • fileName 自定义接口所属文件名称

    默认的接口所属文件处理规则为: 取去除原始路径开头可能存在的 /api后的第一个单词。 如: 接口 /api/user/info/{id} /api/user/changePswd 会放到 user.ts 文件里; 如果接口路径上有统一的前缀,如 /prefix/api/dept/list,那么所有的接口都将被放到 prefix.ts 文件里;

    你可以通过 fileName 自定义这个规则,配置示例:

    {
      apiList: [
        {
          /**
           * 自定义接口所属文件名称
           * @param url 接口路径(pathRewrite 后的路径)
           * @param originUrl 接口原始路径(接口文档上的路径)
           **/
          fileName: ({ url, originUrl }) => {
            // 如:
            return 'myApi' // 将所有的接口都放到 myApi.ts 文件里
            // 再如:
            // return originUrl.replace(/^\/prefix\/api\//, '').split('/')[0] //  '/prefix/api/dept/list' 放到 dept.ts 里
          },
        },
      ]
    }
  • typeMap 自定义服务端数据类型和前端数据类型的映射关系

    默认的映射关系为:

    | 服务端数据类型 | 前端 ts 类型 | | -------------- | ------------ | | integer | number | | integer(int32) | number | | integer(int64) | string | | float | number | | number | number | | double | string | | long | string | | string | string | | boolean | boolean | | date | string | | date-time | string | | uri | string | | url | string | | file | File | | object | any |

    配置示例:

    {
      apiList: [
        typeMap: {
          int64: 'number',  // 服务端的 int64 类型数据将被定义成 number 类型
        },
      ]
    }

2. mock 配置选项:

| 配置项 | 是否必传 | 类型 | 默认值 | 说明 | | ---------- | -------- | ---------------------- | ------ | -------------------------------------------------------------------- | | port | N | Number | 8090 | 本地启动的 mock 服务端口号 | | rewrite | N | Function | / | 接口路径重写 | | fieldRules | N | Record<string, string> | / | 自定义 mock 生成规则,参考 mockjs |

示例

1. 简单示例

import { type UserConfig } from '@cxxgo/genapi'

const config: UserConfig = {
  apiList: [
    {
      swaggerUrl: '', // 接口文档 json 地址
      outputDir: '/src/api', // 生成结果的输出路径
    },
  ],
  httpTpl: "import request from './request/index'", // 文件头部引入的内容,通常用于引入封装的请求方法
  // 自定义 api 结构
  apiBody: ({ url, method, summary, name, outputInterface, pstr1, pstr2, pstr3 }) => {
    const quotation = pstr3 ? '`' : "'" // 引号类型
    return `
        /** ${summary || '无注释'} */
        export function ${name}  (${pstr1}) :Promise<${outputInterface || undefined}>{
          ${pstr3 ? pstr3 : ''}
          return Http.${method}(${quotation}${url}${quotation}, ${pstr2})
        }`
  },
}

export default config

基于以上配置,假如现在有以下三个接口:

get:   /api/user/info/{id}
post:  /api/user/changePswd
get:   /api/dept/list

将生成以下格式的接口文件和数据:

|-src
  |-api
     _interfaces.ts  // 自动生成的类型文件,名称固定为 _interfaces
     user.ts  // 接口文件
     dept.ts // 接口文件

src/api/user.ts 内容:

import request from './request/index'
import { ExampleModel1, ExampleModel2, ExampleModel3 } from './_interfaces.ts'

/** 获取用户信息 */
// 注:'data: { id: string }' 这一串即 apiBody 中的 pstr1
export function userInfo(data: { id: string }): Promise<ExampleModel1> {
  const { id } = data // 注: 'const { id } = data' 这一串即 apiBody 中的 pstr3
  return request.get(`/api/user/info?${id}`)
}

/** 用户修改密码 */
export function userChangePswd(data: ExampleModel2): Promise<ExampleModel3> {
  return request.post('/api/user/changePswd', data) // 注:'data' 即 apiBody 中的 pstr2
}

src/api/dept.ts 内容:

import request from './request/index'
import { ExampleModel4 } from './_interfaces.ts'

/** 获取部门列表 */
export function deptList(): Promise<ExampleModel4> {
  return request.get('/api/dept/list')
}

2. 更多配置示例

import { type UserConfig } from '@cxxgo/genapi'
const config: UserConfig = {
  apiList: [
    {
      swaggerUrl: 'http://xxx1', /
      outputDir: './src/api1',
      gen: true,
      exclude: [/api\/test/, '/api/xxx/xxx'],
    },
    {
      swaggerUrl: 'http://xxx2',
      outputDir: './src/api2',
      gen: true,
      include: [/api\/user/, '/api/dept/list'],
      // 使用不同的头部引入的内容
      httpTpl:"const myRequest:any=()=>{}",
      pathRewrite: () => {}, // 使用不同的 `pathRewrite` 生成规则
      fileName: () => {}, // 使用不同的 `fileName` 生成规则
      apiName: () => {}, // 使用不同的 `apiName` 生成规则
      apiBody: () => {}, // 使用不同的 `apiBody` 生成规则
      typeMap: {
        int64: 'number',
      },
    },
  ],
  httpTpl: 'const request:any=()=>{}',
  pathRewrite: ({ url }) => {},
  fileName: ({ url, originUrl }) => {},
  apiName: ({ url, originUrl ,method,defaultApiName}) => {},
  apiBody: ({ url, originUrl, method, summary, name, outputInterface, pstr1, pstr2, pstr3 }) => {},
  //  mock 相关
  mock: {
    /**
     * mock 路径重写
     * @param url 接口路径(pathRewrite 后的路径)
     */
    rewrite: ({url}) => {
      return `/api/${url}`
    },
    port: 8090,  // mock 服务端口号, 默认 8090
    // 工具本身有内置的 mock 生成规则,当然你也可以使用 fieldRules 进行自定义
    fieldRules: {
      code: 200,   // 完全匹配,值为数字
      size: '20',     // 完全匹配,值为字符串
      created: '@datetime',       // 完全匹配,值为mock字符串, http://mockjs.com/examples.html
      // 完全匹配,值为函数
      total: () => {
        return +this.size * 10 || 100
      },
      '/url/': '@url',   // 正则匹配,值为mock字符串
      loginStatus: 'ONLINE|OFFLINE|',   // loginStatus 的 mock 结果为 'ONLINE' 或 'OFFLINE' 或 '',若不期望生成空字符串,去除末尾的竖线即可
    },
  },
}
export default config

使用 mock 服务

使用方式 1

执行 genapi mock-server, 会启动 http://locahost:8090 的本地 mock 服务,直接访问这个地址即可

使用方式 2

在项目入口文件中 import '@cxxgo/genapi/mock/index'

(基于 better-mock, XHR 和 fetch 请求均可以拦截)