Fastify ベストプラクティス #5: Swaggerドキュメントの生成

公開日 2025年6月24日
更新日 2025年6月26日
11 分で読める
TypeScript

サーバーサイドAPIを開発する際、正確かつリアルタイムで理解しやすいAPIドキュメントを維持することは、チームの協力効率と外部開発者の体験を向上させる鍵となります。手作業でのドキュメント作成は時間がかかるだけでなく、コードとドキュメントの不整合が非常に起こりやすいです。幸いなことに、Fastifyのエコシステムには@fastify/swagger@fastify/swagger-uiという2つの強力なツールがあり、これらを使うことで私たちのコード(特にZodスキーマ)を直接、プロフェッショナルでインタラクティブなSwaggerドキュメントに変換し、「コード即ドキュメント」を実現できます。

まず、関連する依存関係をインストールする必要があります。

npm install @fastify/swagger @fastify/swagger-ui

Swaggerプラグインの設定

次に、Fastifyインスタンスにこれら2つのプラグインを登録します。独立したプラグインファイル(例: plugins/swagger.ts)で設定を行うのが良いプラクティスです。

ここでの核心は、@fastify/swaggerが、私たちが前回の記事で強く推奨したZodスキーマを理解できるようにすることです。

import swagger from '@fastify/swagger';
import swaggerUi from '@fastify/swagger-ui';
import fastify, { FastifyInstance } from 'fastify';
import { jsonSchemaTransform } from 'fastify-type-provider-zod';

export const setupSwagger = async (server: FastifyInstance) => {
  // swaggerコアプラグインを登録
  await server.register(swagger, {
    // 重要:swaggerがZodスキーマをサポートするようにする
    transform: jsonSchemaTransform,
    openapi: {
      openapi: '3.0.0', // OpenAPIバージョン
      info: {
        // ドキュメントの基本情報
        title: 'Fastify ベストプラクティスプロジェクト API',
        description: 'これはサンプルプロジェクトのAPIドキュメントです',
        version: '0.1.0',
      },
      servers: [
        // APIサーバーのリスト
        {
          url: `http://127.0.0.1:8080`,
          description: '開発サーバー',
        },
      ],
      tags: [
        // API分類タグ
        { name: 'user', description: 'ユーザー関連API' },
        { name: 'health', description: 'ヘルスチェックAPI' },
      ],
      // オプション:グローバルなセキュリティ認証設定を追加
      components: {
        securitySchemes: {
          bearerAuth: {
            type: 'http',
            scheme: 'bearer',
            bearerFormat: 'JWT',
          },
        },
      },
      security: [
        {
          bearerAuth: [],
        },
      ],
    },
  });

  // swagger UIプラグインを登録し、可視化されたドキュメント画面を提供
  await server.register(swaggerUi, {
    routePrefix: '/doc', // swaggerドキュメントのアクセスパス
    uiConfig: {
      docExpansion: 'list', // 'full', 'list', 'none'
      deepLinking: true,
    },
  });
};

jsonSchemaTransformの役割

お気づきかもしれませんが、ここでの鍵はtransform: jsonSchemaTransformという設定です。fastify-type-provider-zodからインポートされるこの関数は、いわば橋渡しのような役割を果たします。ルートで定義したZodスキーマを、Swagger(OpenAPI仕様)が要求するJSON Schema形式に自動的に変換してくれるのです。これがなければ、Swaggerは私たちのZod型定義を理解できません。

ルートにドキュメント情報を追加する

プラグインの設定が完了したら、次は各APIルートのschemaオプションにメタデータを追加する必要があります。Swaggerはこれらの情報を読み取ってドキュメントを生成します。

具体的な例を見てみましょう。

import { FastifyInstance } from 'fastify';
import type { ZodTypeProvider } from 'fastify-type-provider-zod';
import { z } from 'zod';

const routes = async (fastify: FastifyInstance) => {
  fastify.withTypeProvider<ZodTypeProvider>().get(
    '/user/:id', // APIのURL
    {
      schema: {
        summary: '単一ユーザー情報の取得',
        description: 'ユーザーIDに基づいて詳細情報を照会します。',
        tags: ['user'], // APIの分類
        params: z.object({
          id: z.string().uuid().describe('ユーザーの一意ID (UUID形式)'),
        }),
        response: {
          200: z
            .object({
              id: z.string().uuid(),
              name: z.string(),
              email: z.string().email(),
            })
            .describe('成功レスポンス'),
          404: z
            .object({
              message: z.string(),
            })
            .describe('ユーザーが見つからない場合のレスポンス'),
        },
        // このAPIがbearerAuth認証を必要とすることを示す
        security: [{ bearerAuth: [] }],
      },
    },
    async (req, reply) => {
      // ... ビジネスロジック ...
      const user = { id: req.params.id, name: 'きかちゃん', email: 'kika-chan@example.com' };
      return reply.status(200).send(user);
    },
  );
};

export default routes;

ヒント:Zodの.describe()メソッドは非常に便利なテクニックです。jsonSchemaTransformは賢くその内容を読み取り、Swagger UIのフィールド説明として表示してくれるため、APIドキュメントがより明確になります。

まとめ

上記の設定を通じて、私たちはプロジェクトのためにプロフェッショナルでインタラクティブなAPIドキュメントを生成しただけではありません。最も重要なのは、このドキュメントが私たちのコードと完全に同期した「生きたドキュメント」であるということです。あなたのZodスキーマが変更されるたびに、ドキュメントは自動的に更新されます。これにより、手作業でのドキュメント管理に起因するコードとドキュメントの不整合という悩みから完全に解放されます。これは開発効率とAPIの保守性を大幅に向上させ、現代のサーバーサイド開発において不可欠な要素です。


私のオープンソースプロジェクトでは、Swaggerに関する設定を独立したプラグイン(04.swagger.plugin.ts)にカプセル化し、fastify-autoloadを通じて自動的に読み込んでいます。よろしければ参考にしてください。

fastify-best-practice on GitHub

概要

技術的洞察、経験、思考を共有する個人ブログ

クイックリンク

お問い合わせ

  • Email: hushukang_blog@proton.me
  • GitHub

© 2025 CODE赤兎. 無断転載禁止