前端根据swagger生成接口文件(pont工具的应用)

2,913 阅读1分钟

本文介绍的工具是 pont , 在法语中是“桥”的意思,寓意着前后端之间的桥梁。

Pont 把 swagger、rap、dip 等多种接口文档平台,转换成 Pont 元数据。Pont 利用接口元数据,可以高度定制化生成前端接口层代码,接口 mock 平台和接口测试平台。 image.png

1 安装依赖

1.1 使用命令行 npm i pont-engine -D
命令行模式 pont generate 具体查看官网

1.2 使用vscode插件,vscode-pont(推荐一旦检测到项目中存在有效的 pont-config.json 配置文件,插件便会启动。你将在插件底部看到如下状态栏: image.png 使用方法

2 新建pont-config.json

多数据源

{
  "outDir": "../src/api",
  "origins": [
    {
      "originUrl": "http://192.168.33.115:8202/szba-intelligence/v2/api-docs",
      "name": "intelligence",
      "usingMultipleOrigins": true
    },
    {
      "originUrl": "http://192.168.33.115:8201/szba-home/v2/api-docs",
      "name": "home",
      "usingMultipleOrigins": true
    }
  ],
  "templatePath": "./serviceTemplate",
  "mocks": {
    "enable": true,
    "port": 8081
  },
  "prettierConfig": {
    "useTabs": false,
    "tabWidth": 2,
    "printWidth": 100,
    "singleQuote": true,
    "trailingComma": "none",
    "bracketSpacing": true,
    "semi": false
  }
}


3 定义自己的template文件(模板)

复写默认的class

/* eslint-disable */

import { CodeGenerator, Interface } from 'pont-engine'
/**
 * @desc 获取请求的URL
 */
export default class MyGenerator extends CodeGenerator {
  constructor(surrounding, outDir = '') {
    super()
    this.surrounding = surrounding
  }
  getInterfaceContent(inter: Interface) {
    let url = inter.path
    let isIdentification = ''
    const identification = '{'
    let paramsArray = []
    if (url.includes(identification)) {
      const result = url.split(identification)[0]
      url = `${result}`
      inter.parameters.forEach((item) => {
        if (item.in !== 'header') {
          paramsArray.push(item.name)
        }
      })
      isIdentification = '+data?.' + paramsArray.join('')
    }
    const paramsCode = inter.getParamsCode()
    const Interfaces = inter.getParamsCode().replace(/class/, 'interface')
    const method = inter.method.toUpperCase()
    const description = inter.description.replace(/(\n|\s)/g, '')
    const contentType =
      inter.consumes && inter.consumes.length ? inter.consumes[0] : 'application/json'

    // 判断参数是否可选
    const isRequired = inter.parameters.some((item) => item.in === 'path' && item.required)
      ? ''
      : '?'

    // 找出tag,赋值对应的host
    let tag = ''
    for (const iterator of this.dataSource.mods) {
      const apis = iterator.interfaces
      if (apis) {
        for (const api of apis) {
          if (api.description.replace(/\n/g, '') === description.replace(/\n/g, '')) {
            tag = iterator.name
          }
        }
      }
    }

    return `


    import request from '@/utils/request';
    import * as defs from '../../baseClass';

    import { useGlobSetting } from '@/utils/useGlobSetting'

    const allConfig: any = useGlobSetting()
    let apiHost = allConfig.apiHost
     for (const key in allConfig) {
       if(key === '${tag}') {
        apiHost = allConfig[key]
       }
    }
    /**
      * @description ${description}
      * @name ${inter.name}
      * @group ${tag}
      */

    ${Interfaces}
    export async function ${inter.name}(data${isRequired}: Params) {
      const options = {
        method: '${method}',
        url: apiHost + '${url}' ${isIdentification},
        ${isIdentification ? '' : 'data,'}
        name: '${description}',
        headers: {
          'Content-Type': '${contentType}'
        }
      }
      return request(options);
    }
    export const init = ${inter.response.initialValue};
   `
  }

  /** 获取所有模块的 index 入口文件 */
  getModsIndex() {
    let conclusion = `
      export {
        ${this.dataSource.mods
          .filter((mod) => mod.name !== 'login')
          .map((mod) => mod.name)
          .join(', \n')}
      };
    `

    // dataSource name means multiple dataSource
    if (this.dataSource.name) {
      conclusion = `
        export const ${this.dataSource.name} = {
          ${this.dataSource.mods.map((mod) => mod.name).join(', \n')}
        };
      `
    }

    return `
      ${this.dataSource.mods
        .filter((mod) => mod.name !== 'login')
        .map((mod) => {
          return `import * as ${mod.name} from './${mod.name}';`
        })
        .join('\n')}

      ${conclusion}
    `
  }

  /** 获取接口类和基类的总的 index 入口文件代码 */
  getIndex() {
    let conclusion = `
      export * from './mods';
    `

    // dataSource name means multiple dataSource
    if (this.dataSource.name) {
      conclusion = `
        export { ${this.dataSource.name} } from './mods/';
      `
    }

    return conclusion
  }
  getModIndex(mod) {
    return `
      /**
       * @description ${mod.description}
       */
      ${mod.interfaces
        .map((inter) => {
          return `import * as ${inter.name} from './${inter.name}';`
        })
        .join('\n')}

      export {
        ${mod.interfaces.map((inter) => inter.name).join(', \n')}
      }
    `
  }
}


4 定义自己的transformTemplate(数据源预处理路径)

// transfrom.ts 根据 Mod.name进行过滤
import { StandardDataSource } from 'pont-engine'

export default function transform(data: StandardDataSource) {
  if (data.name && data.name.includes('*')) {
    data.name = data.name.replace('*', '')
  }
  return data
}

5 生成对应的文件

image.png

6 使用方法

import { qylbPage } from '@api/companyMonit/qylbPage'

qylbPage().then((res) => {
  console.log(res)
})

或者挂载在全局调用也行