現在、NestJSを使って自社サービスを開発しています。
ふと、こう思うんですね。
「開発メンバーとPostmanのコレクションを共有できたら効率上がりそう」と
Postmanは、Swagger Specファイルからインポートすることでコレクションを簡単に作れます(今までは個人が手作業しててつらみがあった)
というわけで、まずは現在開発しているNestJS製のAPIからSwagger Specファイルを作ってみようというお話です。
手順
なんと公式にあります。しかし、ここ1,2年であまり日本語で解説している記事がなかったので、手元で動かしながら書いていきます。
パッケージのインストール
yarn add @nestjs/swagger
bootstrap()
に設定を追記
ここで出力に関するオプションを設定できます。設定内容は公式のママです。
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
+ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import * as bodyParser from 'body-parser';
import { TimeoutInterceptor } from './common/interceptors/timeout.interceptor';
import { AppModule } from './modules/app.module';
const WHITE_LIST = ['http://localhost:3000'];
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new TimeoutInterceptor());
app.enableCors({
origin: WHITE_LIST,
});
app.use(bodyParser.json({ limit: '50mb' }));
app.useGlobalPipes(new ValidationPipe({ stopAtFirstError: true, forbidUnknownValues: false }));
+ const config = new DocumentBuilder()
+ .setTitle('Cats example')
+ .setDescription('The cats API description')
+ .setVersion('1.0')
+ .addTag('cats')
+ .build();
+ const document = SwaggerModule.createDocument(app, config);
+ SwaggerModule.setup('api', app, document);
await app.listen(process.env.APP_PORT || 3000);
}
bootstrap();
Swagger UIを起動する
アプリケーションを起動し
npm run start
(ポートはご自身の環境に置き換えてください)
http://localhost:3000/apiにアクセスすると
現在実装されているAPIの一覧が表示されます(現段階ではタグを付けてない)
本題: JSONをダウンロードする
http://localhost:3000/api-json にアクセスするだけでJSON形式でSwagger Specファイルをダウンロードできます。
とても便利
Postmanにコレクションとしてインポートする
Importing and exporting data | Postman Learning Center
業務関連のAPIなので全ては写しませんが、こんな感じにインポートされます。ヨシ!
オプションを弄っていく
const config = new DocumentBuilder()
.setTitle('Cats example')
.setDescription('The cats API description')
.setVersion('1.0')
.addTag('cats')
+ .addServer('http://localhost:3001') //
+ .addGlobalParameters(
+ {
+ name: 'idToken',
+ in: 'header',
+ schema: { default: '{{idToken}}' },
+ },
+ {
+ name: 'authorization',
+ in: 'header',
+ schema: { default: '{{accessToken}}' },
+ },
+ )
+ .build();
これはTipsですが、
addGlobalParameters()
でschema.defaultに{{環境変数}}
と指定することでPostmanの環境変数を参照してます。
各APIにはこんな感じで設定できます。
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
+ import {
+ ApiBearerAuth,
+ ApiOperation,
+ ApiResponse,
+ ApiTags,
+ } from '@nestjs/swagger';
import { CatsService } from './cats.service';
import { CreateCatDto } from './dto/create-cat.dto';
import { Cat } from './entities/cat.entity';
+ @ApiBearerAuth()
+ @ApiTags('cats')
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Post()
+ @ApiOperation({ summary: 'Create cat' })
+ @ApiResponse({ status: 403, description: 'Forbidden.' })
async create(@Body() createCatDto: CreateCatDto): Promise<Cat> {
return this.catsService.create(createCatDto);
}
SwaggerのSchemaをDTOから作成するには、@ApiProperty()
デコレータを使います。
import { ApiProperty } from '@nestjs/swagger';
export class Cat {
/**
* The name of the Cat
* @example Kitty
*/
name: string;
@ApiProperty({ example: 1, description: 'The age of the Cat' })
age: number;
@ApiProperty({
example: 'Maine Coon',
description: 'The breed of the Cat',
})
breed: string;
}
課題
現プロジェクトでは、NestJSでバリデーターに使うDTOを、RHFのclassValidatorResolver()
を使ってフォームバリデーションにも使いまわしています。
その場合、ApiResponse()
などはクライアント(Next.js)での使用が想定されていないので、next build
がコケるようになってしまいました。
モノレポでDTOを共有している場合はSchemaを生成できないっぽいので注意・工夫が必要です。