npm package: @seer-bigdata/auto-gen-api
Description: 自动生成apifox的接口文件(基于openapi-ts-request再封装)
Latest version: 0.0.6

# @seer-bigdata/auto-gen-api

自动生成apifox的接口文件(基于 [openapi-ts-request](https://www.npmjs.com/package/openapi-ts-request) 再封装)

1. 解决apifox 接口生成时不支持 `moduleId` 的入参问题
2. 再封装 配置文件，支持自定义配置 和 添加默认配置
3. 自定义 配置文件生成逻辑，支持交互问询生成配置文件
4. 修复生成的文件注释不符合预期的情况
   1. 函数注释带特殊符号导致的注释解析错误
   2. type 属性将 title 解析为 描述
5. 新增自动生成自定义泛式文件，用于存放一些和接口操作相关的自定义的泛式类型（在 `{serversPath}/types.ts` 文件）
6. `0,0,5`新增暴露获取接口方法名和method 的方法，对应函数名开头为 `url<Method><Path>`，返回url 和 method ，用于文件上传时部分组件入参是具体url的情况

## 简单使用

### 定义实现 request 方法

自行实现 `request` 方法（用于发送请求） 和 `RequestOptions` 类型，用于被接口文件引入调用
`request` 方法的类型结构如下

```ts title="request.ts"
type RequestProps = {
  method: HttpMethod;
  params?: Record<string, any>;
  body?: Record<string, any>;
  options?: RequestOptions;
};

export type RequestOptions = AxiosConfig;

export function request<T>(url: string, props: RequestProps): Promise<T> {
  // 自定义实现的请求方法
  return axios(url, props.options);
}
```

#### 适配原来的baseHandler 方法

为了兼容原来的 `baseHandler` 方法，需要定义 `request` 方法并内部引用`baseHandler` 方法

```ts title="request.ts"
import { createHandler, HandlerConfig } from './createHandler';

export type RequestOptions = HandlerConfig;

export const request = <Response>(
  url: string,
  props: {
    method: Method;
    params?: Record<string, any>;
    data?: Record<string, any>;
  } & HandlerConfig
) => {
  // 自定义实现的请求方法
  const { method, params, data, ...options } = props;
  return baseHandler<Response>(url, method)(undefined, {
    ...options,
    params,
    data,
  });
};
```

### 生成配置文件

通过 `auto-gen-api.config.ts` 配置文件，可自定义配置 生成的接口文件，首次可以直接执行 `npx @seer-bigdata/auto-gen-api` 生成配置文件

1. `apifoxProjectId` : 要生成的 apifox 项目 id
2. `apifoxToken` : apifox 项目的 token，用于获取接口文档
3. `apifoxModuleId`: apifox 模块id，用于指定要生成的接口模块
4. `requestImportStatement`: 请求库导入语句，默认值 `"import { request , RequestOptions } from '@/services';"`， 如baseUrl 不一样，需要自定义，如`@/services` 需要导出多个 `request` 等方法，需要自定义导入语句 `"import { requestFile as request , RequestOptions } from '@/services';"`

```ts title="auto-gen-api.config.ts"
// 生成了 2 个服务的接口文件
import type { AutoGenApiConfig } from '@seer-bigdata/auto-gen-api';

const config: AutoGenApiConfig = {
  apifoxProjectId: '7006989',
  apifoxToken: '<apifoxToken>',
  serversPath: './src/services/auto-gen-apis/',
  genList: [
    {
      serverDirName: 'files',
      requestImportStatement:
        "import { requestFile as request , RequestOptions } from '@/services';",
      describe: '学校体测-IOT 2.1 - 文件服务',
      apifoxModuleName: '文件服务',
    },
    {
      apifoxModuleId: 6066365,
      serverDirName: 'web',
      requestImportStatement:
        "import { request , RequestOptions } from '@/services';",
      describe: '学校体测-IOT 2.1 - web服务',
      apifoxModuleName: 'web服务',
    },
  ],
};

export default config;
```

### 生成接口文件

默认会生成所有服务的接口文件

```bash
npx @seer-bigdata/auto-gen-api
```

如果只想生成部分服务的接口文件，可添加 `--interactive` 或 `-i` 参数

```bash
npx @seer-bigdata/auto-gen-api --interactive
```

### 新增接口服务

在 `auto-gen-api.config.ts` 中`genList`新增服务配置

1. `apifoxModuleId` 获取：
   - 登录 apifox 后，点击模块（如 `web服务`）,查看 「设置」-> 通用 - 模块 ID

2. `genList` 的配置项 同 `openapi-ts-request` 的配置项

## 定制配置使用

### 修改生成的接口文件路径

默认会在项目根目录下生成 `./src/services/auto-gen-apis/` 目录，可在 `auto-gen-api.config.ts` 中修改 `serversPath` 配置项

单个服务的接口文件会生成在 `./src/services/auto-gen-apis/{serverDirName}/` 目录下，可修改 `serverDirName` 配置项

### 修改生成的接口文件文件名

> 默认为 `${data.method}${upperFirst(camelCase(data.path))}`
> 如 `GET /api/v1/user` 会生成 `getApiV1User` 方法

但有些 `path` 会特别长，导致了生成的方法名过长，可以通过 `GenProps.shortFunNameReplaceList` 配置项，自定义替换方法名

```ts title="auto-gen-api.config.ts" {15-27}
import type { AutoGenApiConfig } from '@seer-bigdata/auto-gen-api';

const config: AutoGenApiConfig = {
  apifoxProjectId: '7006989',
  apifoxToken: '<your-apifox-token>',
  serversPath: './src/services/auto-gen-apis/',
  genList: [
    {
      apifoxModuleId: 6066365,
      serverDirName: 'web',
      requestImportStatement:
        "import { request , RequestOptions } from '@/services';",
      describe: '学校体测-IOT 2.1 - web服务',
      apifoxModuleName: 'web服务',
      /**
       * 自定义函数名替换规则
       * 如
       * PATH: delele `/v1/leagueCompetitionParticipant/releaseDevice/{competitionRecordId}/{participantId}`
       * 正常情况下生成的函数名：`deleteV1LeagueCompetitionParticipantReleaseDeviceRecordIdParticipantId`
       * 配置后生成的函数名 `deleteLcpReleaseDeviceRecordIdParticipantId`
       */
      shortFunNameReplaceList: [
        {
          origin: '/v1/leagueCompetitionParticipant/',
          replace: '/lcp/',
        },
      ],
    },
  ],
};

export default config;
```

:::warning

1. `shortFunNameReplaceList` 在配置了自定义`hook.customFunctionName` 时，不会生效
2. `shortFunNameReplaceList` 只适合在首次引入的接口文件中使用，否则修改了函数名后，可能会导致原来的api函数引用名变更导致报错

:::

### 忽略某些接口的生成

适用于 某些接口 不需要生成的场景

> 继承自 `openapi-ts-request` 的配置项

```ts title="auto-gen-api.config.ts" {15-18}
import type { AutoGenApiConfig } from '@seer-bigdata/auto-gen-api';

const config: AutoGenApiConfig = {
  apifoxProjectId: '7006989',
  apifoxToken: '<your-apifox-token>',
  serversPath: './src/services/auto-gen-apis/',
  genList: [
    {
      apifoxModuleId: 6066365,
      serverDirName: 'web',
      requestImportStatement:
        "import { request , RequestOptions } from '@/services';",
      describe: '学校体测-IOT 2.1 - web服务',
      apifoxModuleName: 'web服务',
      // 设置要忽略的路径
      excludePaths: [/leagueCompetitionSchool/],
      priorityRule: 'both',
    },
  ],
};

export default config;
```

:::warning

1. `priorityRule` 尽量不要选择`exclude`, 因为会导致一些接口类型 `xxxParams` 无法生成

:::

### 部分接口定制化 `options`

适用于 某些接口 定制化 `options` 的场景

> 继承自 `openapi-ts-request` 的配置项

```ts title="auto-gen-api.config.ts" {15-27}
import type { AutoGenApiConfig } from '@seer-bigdata/auto-gen-api';

const config: AutoGenApiConfig = {
  apifoxProjectId: '7006989',
  apifoxToken: '<your-apifox-token>',
  serversPath: './src/services/auto-gen-apis/',
  genList: [
    {
      apifoxModuleId: 6066365,
      serverDirName: 'web',
      requestImportStatement:
        "import { request , RequestOptions } from '@/services';",
      describe: '学校体测-IOT 2.1 - web服务',
      apifoxModuleName: 'web服务',

      hook: {
        customOptionsDefaultValue: (data: OperationObject) => {
          // 给 GET /pets/{id} 接口定制化 options
          if (data?.pathInComment === '/pets' && method.method === 'get') {
            return {
              responseType: 'test',
              // eslint-disable-next-line @typescript-eslint/no-explicit-any
            } as Record<string, any>;
          }
        },
      },
    },
  ],
};
```

生成的效果

```ts title="auto-gen/pet/pet.ts"
/** 可用逗号分隔字符串提供多个状态值。
 GET /pets */
export function getPets({
  params,
  options,
}: {
  // 叠加生成的Param类型 (非body参数openapi默认没有生成对象)
  params: Pet.GetPetsParams;
  options?: RequestOptions;
}) {
  return request<Pet.Pet[]>('/pets', {
    method: 'GET',
    params: {
      ...params,
    },
    pathInComment: '/pets',
    ...{ responseType: 'test' },
    ...(options || {}),
  });
}
```