添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

@antmjs/rapper
TypeScript icon, indicating that this package has built-in type declarations

2.3.22 Public • Published

Rapper 是什么?

注:可以使用@antmjs/api 代替

Rapper 是 TypeScript 的最佳拍档,它可以帮你生成具有类型定义的请求方案。

  • 无需自行书写请求代码,把 HTTP 接口当做函数调用
  • 请求参数/返回数据类型化,静态校验、自动补全快到飞起
  • @antmjs/rapper 是什么?

    基于 Rapper 开发,使配置更灵活,同时增加本地类型同步远程文档重要功能

  • 本地接口类型上传到 rapper 远程文档,本地编码驱动远程文档
  • 自定义请求函数模板,满足不同编程规范
  • package.json scripts 中 添加 { "rap" : "npx rapper"}

    配置 antm.config.js

    rapper: { // 拉取接口地址 apiUrl ? : string ; /** rap 前端地址,默认是 http://rap2.taobao.org */ rapUrl ? : string ; // 生成的文件目录地址 rapperPath ? : string ; // rap登录cookie tokenCookie ? : string ; // rap项目id repositoryId ? : number ;
  • 开始写你的 ts 接口类型, 然后执行 npm run rap
  • rapper 名称对应 接口 ts 类型介绍

    ts 接口类型需要配合 rapper 使用

  • 暂时不支持 url 带 path 参数

    rapper 接口字段名称对应

    interface XY {
      x: number
      y: number
      z: number
    export type IUserInfo = {
      request: {
        // (1)
        age?: string // (2)
      response: {
        // (3)
         * @value true
        success: boolean
        data: {
           * 数组演示 // (4)
           * @rule 123 // (6)
          array: {
             * @value #cname // (5)
            name: string
             * 支持泛型以及接口引用
            other: XY
          }[]
    

    以下是 rapper 中含义

  • 1 [request] 请求参数定义;
  • 2 [age?: string] 入参定义字段名称,必选,类型;
  • 3 [response] 返回数据定义;
  • 4 [jsDoc 描述: 数组演示] 字段简介
  • 5 [jsDoc 关键字:@value #cname] 字段初始值
  • 6 [jsDoc 关键字:@rule 123] 字段生成规则
  • 注意 jsDoc 关键字的值中【@】符号由于转义问题需要替换成【#】或者【\@】或者【/@】

    命令函入参会和 config 合并(命令行优先级更高)

  • --u 上传
  • --d 下载
  • --m xx 指定 moduleId,不传默认提交更改的模块
  • rapper 配置 config 有三种方案

    方案一(推荐)

    通过 antm.config.js 配置 config

    // <!-- antm.config.js文件 -->
    const antmRapper = require('@antmjs/rapper')
    // <!--  使用antm 提供 defineConfig 会有类型提示 -->
    export.default = antmRapper.defineConfig({
      upload: { xx: xx }, // 本地上传 配置
    

    通过 命令行参数执行 config 路径

      $ npx rapper --config  ./config/index.js
    // <!-- ./config/index.js文件 -->
    const antmRapper = require('@antmjs/rapper')
    // <!--  antmRapper 提供 defineConfig 会有类型提示 -->
    export.default = antmRapper.defineConfig({
      upload: { xx: xx }, // 本地上传 配置
      download: { xx: xx } // 远程下载 配置
    

    通过 package.json 配置 antm.rapper

    <!--package.json  文件  -->
      'antm': {
      'rapper': {
        'upload': { xx: xx }, // 本地上传 配置
    

    本地代码类型同步到远程 raper 文档

  • 解析本地文件
  • fetch 方法追加注释 (接口 id 接口模块 id)
  • 格式化 类型
  • 调用 rapper 接口
  • 增量更新实现

  • 每次更新会给文件头部 加一个 MD5 值
  • 初始化会检查合法的文件(符合 formatFunc 结构的文件) MD5 值 对不住
  • 去解析当前文件以及 依赖当前文件的文件
  • 提交变更的模块接口(文件级检查),做不到方法级检查
  • config 接口类型

    interface IConfig {
      // 下载配置
      download: {
         * @param params   rap上填入接口的信息
         * @returns
         * reqTypeName: request类型名称;
         * resTypeName: response类型名称;
         * funcMain: 请求函数体;
        requestFunc?: (params: {
          funcDescription: string
          repositoryId: number
          moduleId: number
          interfaceId: number
          requestUrl: string
          requestMethod: string
          rapUrl: string
        }) => {
          reqTypeName: string
          resTypeName: string
          funcMain: string
         * @param params   rap 上填入的module信息
         * @returns
         * fileName: 模块的文件名称;
         * moduleHeader: 模块头部的banner;
        requestModule?: (params: {
          repositoryId: number
          moduleId: number
          moduleRapUrl: string
          moduleDescription: string
        }) => {
          fileName: string
          moduleHeader: string
        // 自定下载的module
        moduleId?: number
      rapper: {
        // 拉取接口地址
        apiUrl?: string
        /** rap 前端地址,默认是 http://rap2.taobao.org */
        rapUrl?: string
        // 生成的文件目录地址
        rapperPath?: string
        // rap登录cookie
        tokenCookie?: string
        // rap项目id
        repositoryId?: number
      upload: {
        //  模式 type 文件扫描入口是type(需要编译生成fetch)
        //  fetch 文件扫描入口是fetch请求函数(不需要编译)
        mode?: 'type' | 'fetch'
        // 需要解析的文件名称正则
        fileRegex?: string
         * @param params  函数信息
         * @returns
         *  resTypeName: request 类型名称;
         * reqTypeName: response  类型名称;
         * reqUrl: 请求 url;
         * reqMethod: 请求method;
         * interfaceId: 接口id;
        formatFunc?: (params: {
          funcName: string
          body: string
          comment: string
          // 三种函数 定义 会被选中到导出
          funcType: 'CallExpression' | 'FunctionDeclaration' | 'ArrowFunction'
        }) => {
          resTypeName: string
          reqTypeName: string
          reqUrl: string
          reqMethod: string
          interfaceId: number
        } | null
        // 指定下载的 模块id
        moduleId?: number
        // webpack 别名
        alias?: Record<string, string>
      // 内部标识使用 不用管
      __completion?: boolean
      // 是不是上传
      isUpload: boolean
    export type IOptions = Partial<IConfig>

    defaultConfig 会和传进来的 config 合并补全

       const defaultOptions = {
        download: {
          //请求 function 模板
          requestFunc(params) {
            function getFnName(url: string): null | string {
              const fnName = url.match(/\/([.a-z0-9_-]+)\/([a-z0-9_-]+$)/i);
              if (fnName && fnName.length === 3) {
                if (/^\d+\.\d+$/.test(fnName[1])) {
                  return fnName[2];
                return fnName[1] + fnName[2].charAt(0).toUpperCase() + fnName[2].slice(1);
              return null;
            const fnName = getFnName(params.requestUrl);
            if (!fnName) {
              throw new TypeError('接口路径不对,请修改合规');
            const camelCaseName = `${fnName.charAt(0).toUpperCase()}${fnName.slice(1)}`;
            const reqTypeName = `IReq${camelCaseName}`;
            const resTypeName = `IRes${camelCaseName}`;
            return {
              reqTypeName,
              resTypeName,
              funcMain: `
                   * 接口名:${params.funcDescription}
                   * Rap 地址: ${params.rapUrl}?id=${params.repositoryId}&mod=${params.moduleId}&itf=${params.interfaceId}
                  export const ${fnName} = createFetch<${reqTypeName}, ${resTypeName}>('${params.requestUrl}', '${params.requestMethod}')
          //请求 函数共工头(用于引入函数
          requestModule(params) {
            return {
              fileName: params.moduleDescription,
              moduleHeader: `
    /* eslint-disable */
    /* tslint:disable */
    // @ts-nocheck
    import instance from '@/utils/request'
    function createFetch<REQ extends Record<string, unknown>, RES extends {data: any}> (url: string, method: string) {
      return  <T extends boolean = false>(
        data: REQ,
        options?: {
          proxy?: T
          pageError?: boolean
      ): Promise<T extends true ? RES['data'] : RES> => {
        return instance(
            method,
            data,
          options
        rapper: {
          // 拉取接口地址
          apiUrl:
            'http://rap2api.taobao.org/repository/get?id=284428&token=TTDNJ7gvXgy9R-9axC-7_mbi4ZxEPlp6',
          /** rap 前端地址,默认是 http://rap2.taobao.org */
          rapUrl: 'http://rap2.taobao.org',
          rapperPath: './src/actions',
          tokenCookie:
            'aliyungf_tc=f3a5915db08fc3b6de3ec5df0d0b3a5dc07c0b701e44cf4bf98a855799570bfe; koa.sid=2I353u8TTwtrHSdPXdJ9t8Mx5lTOeQFV; koa.sid.sig=D4vYLNcryQ8vcU4GkJJknTi_Fm8',
          repositoryId: 284428,
        upload: {
          mode: 'type' as const,
          // fileRegex 将尝试使用绝对文件路径检测测试文件
          // (/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$
          fileRegex: './src/actions/types/.*(js|jsx|ts|tsx)',
          formatFunc(params) {
            // createFetch<IReqGoodsQbf, IResGoodsQbf>('/c/api/1.0/approve/goods/qbf', 'GET')
            // export const goodsQbf = createFetch<IGoodsQbf['request'], IGoodsQbf['response']>("/c/api/1.0/approve/goods/qbf", "GET");
            const [_, reqTypeName, resTypeName, reqUrl, reqMethod] =
              params.body.match(
                /createFetch<([\w\[\]'"]+),\s+([\w\[\]'"]+)>\(['"]([\s\S]+)['"], ['"]([a-zA-Z]+)['"]\)/,
              ) || [];
            if (!reqTypeName || !resTypeName) {
              return null;
            const matchInterfaceId = params.comment.match(/http:\/\/rap2\.tao[\s\S]+&itf=(\d+)/);
            return {
              resTypeName,
              reqTypeName,
              // 如果返回 null '' undefined 0 等 就会被认为是新的接口,会触发上rap操作
              interfaceId: matchInterfaceId ? Number(matchInterfaceId[1]) : null,
              reqUrl: reqUrl,
              reqMethod: reqMethod,
          // webpack 别名 alias 绝对路径
          alias: {
            '@': './src',
        isUpload: true,
    
  •