DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

Claude CodeでOpenAPIクライアントを自動生成する:型安全SDK・モックサーバー・CI差分検知

OpenAPI仕様書からTypeScriptクライアントを手書きするのは非効率で、型のズレがバグの温床になる。Claude Codeを活用して型安全なSDK自動生成・モックサーバー・CI差分検知のパイプラインを構築する。

openapi-typescriptで型定義を自動生成

openapi-typescriptはOpenAPI 3.x仕様からTypeScript型定義を生成するツール。Claude Codeへの指示例:

openapi.yamlからTypeScript型定義を生成し、
すべてのエンドポイントに対して型安全なクライアントを実装してください。
Enter fullscreen mode Exit fullscreen mode

まずインストールと型生成:

npm install openapi-typescript openapi-fetch
npx openapi-typescript openapi.yaml -o src/types/api.ts
Enter fullscreen mode Exit fullscreen mode

生成される型定義の例(openapi.yamlに/users/{id}がある場合):

// src/types/api.ts(自動生成)
export interface paths {
  "/users/{id}": {
    get: {
      parameters: {
        path: { id: string };
      };
      responses: {
        200: {
          content: {
            "application/json": components["schemas"]["User"];
          };
        };
        404: {
          content: {
            "application/json": components["schemas"]["ErrorResponse"];
          };
        };
      };
    };
  };
}

export interface components {
  schemas: {
    User: {
      id: string;
      name: string;
      email: string;
      createdAt: string;
    };
    ErrorResponse: {
      code: string;
      message: string;
    };
  };
}
Enter fullscreen mode Exit fullscreen mode

openapi-fetchで完全型安全なクライアント

openapi-fetchは生成された型定義を使い、すべてのリクエスト・レスポンスに型チェックを適用するHTTPクライアント。

import createClient from 'openapi-fetch';
import type { paths } from './types/api';

const client = createClient<paths>({
  baseUrl: process.env.API_BASE_URL ?? 'https://api.example.com',
});

// 完全型安全:引数もレスポンスも型推論が効く
async function getUser(id: string) {
  const { data, error } = await client.GET('/users/{id}', {
    params: { path: { id } },
  });

  if (error) {
    // error は ErrorResponse 型
    console.error(error.message);
    return null;
  }

  // data は User 型
  return data;
}

// 存在しないエンドポイントはコンパイルエラーになる
// client.GET('/users/nonexistent', ...); // ← TypeScriptエラー
Enter fullscreen mode Exit fullscreen mode

Claude Codeに「このクライアントにリトライ・タイムアウト・認証ヘッダーを追加して」と指示すると、型安全性を保ったまま拡張してくれる。

モックサーバーでフロントエンド開発を分離

バックエンドが未実装でもOpenAPI仕様からモックサーバーを立ち上げられる。

npm install -D @stoplight/prism-cli
npx prism mock openapi.yaml --port 4010
Enter fullscreen mode Exit fullscreen mode
// テスト・開発環境でモックに切り替え
const client = createClient<paths>({
  baseUrl: process.env.NODE_ENV === 'test'
    ? 'http://localhost:4010'  // Prismモックサーバー
    : 'https://api.example.com',
});
Enter fullscreen mode Exit fullscreen mode

Claude Codeへの活用例:

Prismモックサーバーを使ったインテグレーションテストをVitestで書いてください。
各エンドポイントの正常系・異常系をカバーしてください。
Enter fullscreen mode Exit fullscreen mode

CIで生成ファイルの陳腐化を検知

OpenAPI仕様が更新されたのに生成済み型定義が古いまま → 型のズレでバグ発生。CIで自動検知する。

# .github/workflows/openapi-check.yml
name: OpenAPI Type Check

on:
  pull_request:
    paths:
      - 'openapi.yaml'
      - 'src/types/api.ts'

jobs:
  check-generated:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm ci

      - name: Regenerate types
        run: npx openapi-typescript openapi.yaml -o /tmp/api-generated.ts

      - name: Check for drift
        run: |
          if ! diff -q src/types/api.ts /tmp/api-generated.ts > /dev/null 2>&1; then
            echo "::error::Generated types are outdated. Run: npx openapi-typescript openapi.yaml -o src/types/api.ts"
            diff src/types/api.ts /tmp/api-generated.ts
            exit 1
          fi
          echo "✅ Generated types are up to date"
Enter fullscreen mode Exit fullscreen mode

oasdiffで破壊的変更をPRコメントに表示

oasdiffはOpenAPI仕様の差分を検出し、破壊的変更(Breaking Changes)を識別するツール。

# .github/workflows/breaking-change-check.yml
name: Breaking Change Detection

on:
  pull_request:
    paths:
      - 'openapi.yaml'

jobs:
  oasdiff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Install oasdiff
        run: |
          curl -sSL https://raw.githubusercontent.com/tufin/oasdiff/main/install.sh | sh

      - name: Get base openapi.yaml
        run: git show origin/${{ github.base_ref }}:openapi.yaml > /tmp/openapi-base.yaml

      - name: Detect breaking changes
        id: oasdiff
        run: |
          RESULT=$(oasdiff breaking /tmp/openapi-base.yaml openapi.yaml --format text 2>&1 || true)
          echo "result<<EOF" >> $GITHUB_OUTPUT
          echo "$RESULT" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Comment on PR
        if: steps.oasdiff.outputs.result != ''
        uses: actions/github-script@v7
        with:
          script: |
            const result = `${{ steps.oasdiff.outputs.result }}`;
            const body = result.includes('No breaking changes')
              ? '✅ **No breaking changes detected**'
              : `⚠️ **Breaking changes detected:**

Enter fullscreen mode Exit fullscreen mode

${result}


            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body
            });
```



PRマージ前に破壊的変更を可視化することで、APIクライアントの無言の破損を防ぐ。

## Claude Codeでの実践フロー



```plaintext
1. 「openapi.yamlからsrc/types/api.tsを生成するnpmスクリプトを追加して」
2. 「openapi-fetchを使った型安全クライアントをsrc/client/index.tsに実装して」
3. 「Prismモックサーバーを使ったインテグレーションテストをtests/api.test.tsに書いて」
4. 「型定義の陳腐化を検知するGitHub Actionsワークフローを追加して」
```



各ステップをClaude Codeに指示すれば、仕様書駆動の型安全開発環境が短時間で整う。

## まとめ

1. **openapi-typescriptで型定義を自動生成** — 手書き不要、仕様書が唯一の真実になる
2. **openapi-fetchで完全型安全なHTTPクライアント** — 存在しないエンドポイントへのアクセスはコンパイルエラーで防げる
3. **CI差分検知で陳腐化を即座に検出** — openapi.yaml更新時に未再生成を自動ブロック
4. **oasdiffで破壊的変更をPRに可視化** — APIクライアントの無言の破損をマージ前に防ぐ

Claude Codeとこのツールチェーンを組み合わせることで、API仕様の変更がコードベース全体に安全に伝播する開発フローが実現できる。

---

**Code Review Pack(¥980)** — Claude Codeによる型安全性・APIレビュー・セキュリティチェックのプロンプト集。OpenAPI設計レビューから実装コードのコード品質チェックまでカバー。
[PromptWorksで見る](https://prompt-works.jp)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)