npm package: @pagoda-tools/openapi
Description: openapi
Latest version: 1.0.0-beta.18

# @pagoda-tools/openapi

## 安装

```shell
# install npm
npm install @pagoda-tools/openapi -S

# install yarn
yarn add @pagoda-tools/openapi -S
```

## 文档编写示例

1. 根目录新增配置文件 `openapi.config.js`

```ts
import { defineOpenapiConfig } from '@pagoda-tools/openapi';

export default defineOpenapiConfig({
  info: {
    title: '测试文档标题',
    version: '1.0.0',
  },
  server: [
    {
      url: 'http://www.xxx.com',
      description: '测试环境',
    },
  ],
});
```

2. 在 src 任意目录下新建 `xx.dto.ts`，示例代码如下：

```ts
import {
  defineApi,
  IsInt,
  IsString,
  Type,
  ValidateNested,
} from '@pagoda-tools/openapi';

class User {
  @IsString()
  name: string;
}

export class TestQuery {
  @JSONSchema({
    description: '字段描述',
  })
  a: string;
}

export class TestBody {
  @IsInt()
  @JSONSchema({
    description: '字段描述',
  })
  a: number;

  @ValidateNested({ each: true })
  @Type(() => User)
  @JSONSchema({
    description: '字段描述',
  })
  users: User[];
}

export class TestResponse {
  @IsInt()
  a: number;
}

export default defineApi({
  method: 'get',
  info: {
    summary: '接口名称',
  },
  query: TestQuery,
  body: TestBody,
  response: TestResponse,
});
```

3. 在 `package.json` 的 `scripts` 中新增命令

```json
{
  "scripts": {
    "doc-serve": "pd-openapi serve",
    "export-doc-json": "pd-openapi json"
  }
}
```

4. 执行 `npm run doc-serve`

## openapi.config.js 配置项

```ts
interface OpenapiConfig {
  info?: {
    // 文档标题
    title?: string;
    // 文档描述
    description?: string;
    // 文档版本
    version?: string;
  };
  server?: {
    // 接口环境地址
    url: string;
    // 接口环境地址描述
    description?: string;
  }[];
  compilerOptions?: {
    // 导出文件的文件名 默认为 openapi-json.json
    outputFileName?: string;
    // 导出的openapi版本 默认为 3.0
    openapi?: '2.0' | '3.0';
  };
}
```

## 在 `serverless` 的中间件中添加参数校验

```js
// 本代码仅作为示例代码 可能需要根据项目实际情况自行调整
const url = require('url');
const path = require('path');
const { validateByConfig } = require('@pagoda-tools/swagger-ui');
const { PagodaServerless } = require('pagoda-serverless');

const pdServerless = new PagodaServerless(/*...*/);

async function main() {
  const pathname = url.parse(req.originalUrl).pathname;
  const api = path.parse(pathname).name;
  const apiDir = path.join(
    pathname.replace(`/${RUNTIME_ENV}/platform/`, ''),
    '..'
  );
  const configPath = `../${apiDir}/dto/${api}.dto.js`;

  // 判断是否存在对应接口的 dto 文件
  if (existsSync(path.join(__dirname, configPath))) {
    const swaggerConfig = require(configPath).default;

    const errors = await validateByConfig(swaggerConfig, req);

    if (errors?.length) {
      const error = errors[0];
      const { constraints } = error;

      throw new pdServerless.ParamsException({
        prop: error.property,
        message: constraints[Object.keys(constraints)[0]],
      });
    }
  }

  middlewareCallback(true);
}

pdServerless.executeMain(main, {
  returnRes: false,
});
```

## 在 `serverless` 的中编写 dto 结构示例

```
.
├── src
│   ├── test
│   │   ├── dto
|   |   |   ├── getUser.dto.js
|   |   |   ├── getList.dto.js
|   |   ├── getUser.js
|   |   ├── getList.js
```

## 相关链接

- `IsInt` 等修饰器参考 [class-validator](https://github.com/typestack/class-validator#validation-decorators)