mcpField
O
openapi-codegen

openapi-codegen

github.com/claude-dev-suite開発4659 回インストール2 日前に更新
リポジトリ

openapi-codegen について

OpenAPI ドキュメントからの型や API クライアントの生成、tRPC ルーターの OpenAPI 出力を扱う、TypeScript 開発者向けのコーディングスキルです。仕様の検証、自動生成、生成時の問題への対処も説明します。

主な機能

  1. 01OpenAPI から TypeScript 型を生成
  2. 02fetch または axios の API クライアント生成
  3. 03テンプレートによる出力のカスタマイズ
  4. 04tRPC ルーターを OpenAPI に出力
  5. 05生成の検証と自動化

活用シーン

  1. 01TypeScript プロジェクトに型付き API 契約を追加
  2. 02ローカルまたはリモートの仕様からクライアントを生成
  3. 03OpenAPI ドキュメントを通じて tRPC エンドポイントを公開

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill openapi-codegen

インストール後、Claude Code で/openapi-codegenを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

quick-ref/
openapi-generator.md
openapi-typescript.md
swagger-typescript-api.md
trpc-openapi.md

詳細

OpenAPI コード生成のコア知識

深い知識:包括的なドキュメントについては、technology: openapi-codegen を指定して mcp__documentation__fetch_docs を使用してください。

openapi-typescript(型のみ)

OpenAPI スキーマから TypeScript の型を生成します。軽量で、実行時の処理はありません。

# Installation
npm install -D openapi-typescript

# Generate types
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts
npx openapi-typescript https://api.example.com/openapi.json -o ./src/types/api.ts
生成された型の使い方
import type { paths, components } from './types/api';

// Schema types
type User = components['schemas']['User'];
type CreateUserDto = components['schemas']['CreateUserDto'];

// Request/Response types
type CreateUserRequest = paths['/users']['post']['requestBody']['content']['application/json'];
type UserResponse = paths['/users/{id}']['get']['responses']['200']['content']['application/json'];
type UsersListResponse = paths['/users']['get']['responses']['200']['content']['application/json'];

// Path parameters
type UserPathParams = paths['/users/{id}']['get']['parameters']['path'];
openapi-fetch との併用
import createClient from 'openapi-fetch';
import type { paths } from './types/api';

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

// Fully typed requests
const { data, error } = await client.GET('/users/{id}', {
  params: { path: { id: '123' } },
});

const { data } = await client.POST('/users', {
  body: { name: 'John', email: '[email protected]' },
});

// Query parameters
const { data } = await client.GET('/users', {
  params: { query: { status: 'active', page: 1 } },
});

openapi-generator-cli(フルクライアント)

fetch/axios の実装を含む、完全な API クライアントを生成します。

# Installation
npm install -D @openapitools/openapi-generator-cli

# Generate TypeScript Fetch client
npx @openapitools/openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-fetch \
  -o ./src/api-client

# Generate TypeScript Axios client
npx @openapitools/openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-axios \
  -o ./src/api-client
設定ファイル
# openapitools.json
{
  "$schema": "https://raw.githubusercontent.com/OpenAPITools/openapi-generator-cli/master/apps/generator-cli/src/config.schema.json",
  "spaces": 2,
  "generator-cli": {
    "version": "7.0.0",
    "generators": {
      "typescript-client": {
        "generatorName": "typescript-fetch",
        "output": "#{cwd}/src/api-client",
        "inputSpec": "#{cwd}/openapi.yaml",
        "additionalProperties": {
          "supportsES6": true,
          "npmName": "@myorg/api-client",
          "typescriptThreePlus": true,
          "withInterfaces": true
        }
      }
    }
  }
}
生成されたクライアントの使い方
import { Configuration, UsersApi } from './api-client';

const config = new Configuration({
  basePath: 'https://api.example.com',
  accessToken: () => localStorage.getItem('token') || '',
});

const usersApi = new UsersApi(config);

// Typed API calls
const users = await usersApi.listUsers({ status: 'active' });
const user = await usersApi.getUserById({ id: '123' });
const newUser = await usersApi.createUser({
  createUserDto: { name: 'John', email: '[email protected]' },
});

swagger-typescript-api

テンプレートに対応した、高速でカスタマイズ可能なジェネレーターです。

# Installation
npm install -D swagger-typescript-api

# Generate
npx swagger-typescript-api -p ./openapi.yaml -o ./src/api -n api.ts
設定
npx swagger-typescript-api \
  -p ./openapi.yaml \
  -o ./src/api \
  -n api.ts \
  --axios \                    # Use axios instead of fetch
  --modular \                  # Separate files per tag
  --route-types \              # Generate route types
  --extract-request-body \     # Extract request body types
  --extract-response-body      # Extract response body types
生成されたクライアントの使い方
import { Api } from './api/api';

const api = new Api({
  baseUrl: 'https://api.example.com',
  securityWorker: () => ({
    headers: { Authorization: `Bearer ${getToken()}` },
  }),
});

// Typed API calls
const users = await api.users.usersList({ status: 'active' });
const user = await api.users.usersDetail('123');
const newUser = await api.users.usersCreate({
  name: 'John',
  email: '[email protected]',
});

trpc-openapi(tRPC を OpenAPI としてエクスポート)

tRPC ルーターから OpenAPI 仕様を生成します。外部 API 利用者に役立ちます。

npm install trpc-openapi
OpenAPI エンドポイントの定義
import { initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';
import { z } from 'zod';

const t = initTRPC.meta<OpenApiMeta>().create();

export const appRouter = t.router({
  getUser: t.procedure
    .meta({
      openapi: {
        method: 'GET',
        path: '/users/{id}',
        tags: ['users'],
        summary: 'Get user by ID',
      },
    })
    .input(z.object({ id: z.string() }))
    .output(z.object({
      id: z.string(),
      name: z.string(),
      email: z.string(),
    }))
    .query(({ input }) => getUserById(input.id)),

  createUser: t.procedure
    .meta({
      openapi: {
        method: 'POST',
        path: '/users',
        tags: ['users'],
        summary: 'Create a new user',
      },
    })
    .input(z.object({
      name: z.string(),
      email: z.string().email(),
    }))
    .output(z.object({
      id: z.string(),
      name: z.string(),
      email: z.string(),
    }))
    .mutation(({ input }) => createUser(input)),
});
OpenAPI ドキュメントの生成
import { generateOpenApiDocument } from 'trpc-openapi';
import { appRouter } from './router';

const openApiDocument = generateOpenApiDocument(appRouter, {
  title: 'My API',
  version: '1.0.0',
  baseUrl: 'https://api.example.com',
});

// Save to file
import fs from 'fs';
fs.writeFileSync('./openapi.json', JSON.stringify(openApiDocument, null, 2));
REST ハンドラー
import { createOpenApiNextHandler } from 'trpc-openapi';
import { appRouter } from './router';

// Next.js API route: pages/api/[...trpc].ts
export default createOpenApiNextHandler({
  router: appRouter,
  createContext: () => ({}),
});

本番環境への対応

CI/CD との統合
# .github/workflows/generate-client.yml
name: Generate API Client

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

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

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

      - name: Install dependencies
        run: npm ci

      - name: Generate types
        run: npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts

      - name: Check for changes
        id: check
        run: |
          if git diff --quiet src/types/api.ts; then
            echo "changed=false" >> $GITHUB_OUTPUT
          else
            echo "changed=true" >> $GITHUB_OUTPUT
          fi

      - name: Commit and push
        if: steps.check.outputs.changed == 'true'
        run: |
          git config --local user.email "[email protected]"
          git config --local user.name "API Generator Bot"
          git add src/types/api.ts
          git commit -m "chore: regenerate API types"
          git push
パッケージスクリプト
{
  "scripts": {
    "generate:types": "openapi-typescript ./openapi.yaml -o ./src/types/api.ts",
    "generate:client": "openapi-generator-cli generate -c openapitools.json",
    "generate:all": "npm run generate:types && npm run generate:client",
    "precommit": "npm run generate:types && git add src/types/api.ts"
  }
}
ウォッチモードでの開発
# openapi-typescript with watch
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts --watch

# Or use nodemon
npx nodemon --watch openapi.yaml --exec "npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts"
生成前の検証
# Validate spec first
npx @redocly/cli lint openapi.yaml

# Then generate
npx openapi-typescript ./openapi.yaml -o ./src/types/api.ts
メトリクスの監視
メトリクス目標
生成された型のカバレッジエンドポイントの 100%
生成を含むビルド時間< 30s
生成後の型エラー0
仕様の検証エラー0
チェックリスト
  • CI で OpenAPI 仕様を検証する
  • 仕様変更時に型を自動生成する
  • 生成コードをコミットするか、gitignore に追加する
  • ジェネレーター CLI のバージョンを固定する
  • カスタムテンプレートを文書化する
  • API クライアントの初期化方法を文書化する
  • エラー処理のパターンを文書化する
  • クライアントの認証設定を行う
  • 破壊的変更を検出する
  • 生成コードをテストする

このスキルを使用しない場合

  • OpenAPI 仕様を記述する場合(openapi スキルを使用)
  • GraphQL の型を生成する場合(graphql-codegen スキルを使用)
  • tRPC の型安全な API を使用する場合(trpc スキルを使用)
  • API クライアントを手動で実装する場合
  • 手動での型定義で十分なシンプルな API の場合

アンチパターン

アンチパターン問題点解決策
生成コードを git にコミットするマージ競合、コードの陳腐化.gitignore に追加し、CI/ビルド時に生成する
ジェネレーター CLI のバージョンを管理しない出力が一貫しないpackage.json でジェネレーターのバージョンを固定する
生成されたファイルを手動で編集する再生成時に変更が失われる生成コードを拡張またはラップする
生成前に検証しない無効な型が生成されるまず @redocly/cli で仕様を検証する
チーム内で異なるジェネレーターを使用する型に一貫性がなくなるジェネレーターを 1 つに統一する
キャッシュせずにリモート仕様から生成するビルドが遅くなり、ネットワークに依存する仕様をローカルにキャッシュするか、スキーマレジストリを使用する
仕様変更時に更新しない型と実行時の動作が一致しなくなる仕様の更新時に CI で生成を実行する
生成コードにエラー処理がないエラー時の UX が悪くなる生成されたクライアントをエラー処理でラップする

すばやいトラブルシューティング

問題考えられる原因解決策
生成に失敗するOpenAPI 仕様が無効@redocly/cli lint で検証する
生成後に型エラーが発生する仕様が API と一致していない仕様が実際のレスポンスと一致するか確認する
型が不足している仕様が不完全、または参照が壊れているすべての $refs が解決されることを確認し、不足しているスキーマを追加する
意図しない HTTP クライアントが生成されるジェネレーターの設定が一致していない-g フラグまたはジェネレーター設定を確認する
循環参照エラーが発生するスキーマが自身を参照しているdiscriminator を使用するか、スキーマをフラット化する
生成に時間がかかる仕様ファイルが大きい仕様を分割するか、一部のみを生成する
認証が機能しないセキュリティスキームが設定されていないsecurityWorker またはトークン設定を追加する
「Cannot find module」エラーが発生する生成が完了していない生成エラーを確認し、再実行する
型の競合が発生する複数のジェネレーターが実行されているジェネレーターを 1 つだけ使用し、他を削除する

Reference Documentation

コメント