nestjs swagger 怎么构建统一响应

47 阅读1分钟

提示

本文章只有代码, 没有分析逻辑

效果图

image.png

先看代码

统一响应结构体

import { ApiProperty, ApiSchema } from '@nestjs/swagger';

@ApiSchema({ name: '基础响应' })
export class AppApiResponse<T = any> {
  @ApiProperty({ description: '状态码', example: 200 })
  code: number;
  @ApiProperty({ description: '消息', example: '成功' })
  msg: string;
  @ApiProperty({ description: '数据' })
  data: any;
  constructor(code: number, msg: string, data: T) {
    this.code = code;
    this.msg = msg;
    this.data = data;
  }
}

@ApiSchema({ name: '分页响应' })
export class PagerResponse<T> {
  @ApiProperty({ description: '数据' })
  items: T[];
  @ApiProperty({ description: '当前页码', example: 1 })
  page: number;
  @ApiProperty({ description: '总数', example: 10 })
  total: number;
  @ApiProperty({ description: '每页数量', example: 10 })
  pageSize: number;
  @ApiProperty({ description: '总页数', example: 1 })
  totalPage: number;
  constructor(
    items: T[],
    page: number,
    total: number,
    pageSize: number,
    totalPage: number,
  ) {
    this.items = items;
    this.page = page;
    this.total = total;
    this.pageSize = pageSize;
    this.totalPage = totalPage;
  }
}

swagger装饰器


import { applyDecorators, Type } from '@nestjs/common';
import {
  ApiExtraModels,
  ApiOkResponse,
  ApiResponseSchemaHost,
  getSchemaPath,
} from '@nestjs/swagger';
import { AppApiResponse, PagerResponse } from 'src/types/response';

export function SuccessResponse<T extends Type<any>>(
  model?: T,
  config?: { pager?: boolean; array?: boolean },
) {
  const baseTypeNames = ['String', 'Number', 'Boolean'];
  const { pager = false, array = false } = config || {};
  let prop: ApiResponseSchemaHost['schema']['properties']['data'];
  if (!model) {
    prop = {
      default: null,
      type: 'null',
    };
  } else if (pager) {
    prop = {
      allOf: [
        {
          $ref: getSchemaPath(PagerResponse),
        },
        {
          properties: {
            items: {
              $ref: getSchemaPath(model),
            },
          },
        },
      ],
    };
  } else if (array) {
    prop = {
      type: 'array',
      items: { $ref: getSchemaPath(model) },
    };
  } else if (model) {
    if (baseTypeNames.includes(model.name)) {
      prop = {
        type: model.name.toLowerCase(),
      };
    } else {
      prop = {
        $ref: getSchemaPath(model),
      };
    }
  }
  return applyDecorators(
    model
      ? ApiExtraModels(model, AppApiResponse, PagerResponse)
      : ApiExtraModels(AppApiResponse, PagerResponse),
    ApiOkResponse({
      description: '成功',
      schema: {
        allOf: [
          {
            $ref: getSchemaPath(AppApiResponse),
          },
          {
            properties: {
              data: prop,
            },
          },
        ],
      },
    }),
  );
}

通过 schema 自定义模型, 通过 $ref 关联模型路径, 但是swagger没有自动引入模型, 所以需要通过ApiExtraModels手动引入一下模型