API ドキュメントジェネレーター
既存のルートハンドラーコードから API ドキュメントを抽出します。ソースコードを読み取り、スキーマを推論し、OpenAPI 仕様、TypeScript 型、実行可能な curl の例を生成します。これは設計意図からではなく、実際の実装から生成されます。
アクティベーショントリガー
アクティベーション対象: "API ドキュメントを生成", "コードから OpenAPI", "エンドポイントを文書化", "API リファレンス", "Swagger 生成", "エンドポイントドキュメント", "API 型を作成", "API の curl 例"
対象外: API のゼロからの設計 --> api-architect | ソースコードなしでの OpenAPI 作成 --> openapi-spec-writer | API テスト --> test-automation-expert
コア機能
- Express、Next.js App Router、Next.js Pages API ルート、Fastify、Hono ハンドラーからルート定義を抽出
- TypeScript 型、Zod スキーマ、またはランタイムバリデーションからリクエスト/レスポンススキーマを推論
- 正確なパスパラメータ、クエリ文字列、リクエストボディを含む OpenAPI 3.0/3.1 仕様を生成
- 実際の API コントラクトに一致する TypeScript 型定義を生成
- すべてのエンドポイントに対して、現実的なサンプルデータを使用した curl の例を作成
- ミドルウェアチェーンをトレースして認証要件を文書化
- レート制限設定を特定し、エンドポイントごとの制限を文書化
- ハンドラー内の throw/return パターンを分析してエラーレスポンスをカタログ化
- 未ドキュメントのエンドポイント(存在するが JSDoc やスキーマがないルート)を検出
フレームワーク検出
生成を開始する前に、フレームワークを特定します。抽出戦略はフレームワークによって大きく異なります。
Express / Express 類似フレームワーク
シグナル: app.get(), router.post(), express.Router()
ルートソース: app._router.stack または明示的なルーターファイル
ミドルウェアチェーン: 認証検出には app.use() の順序が重要
ルート登録パターンを探します:
router.get('/users/:id', authenticate, getUser)-- ハンドラーの前のミドルウェアは認証が必要であることを意味しますapp.use('/api/v1', rateLimiter({ max: 100 }), apiRouter)-- レート制限がサブツリーに適用されます
Next.js App Router
シグナル: GET, POST, PUT, DELETE, PATCH をエクスポートする route.ts ファイル
ルートソース: app/api/ のファイルシステム規則
ミドルウェアチェーン: ディレクトリ境界の middleware.ts
パスパラメータはフォルダー名から取得されます: app/api/users/[id]/route.ts --> /api/users/{id}
Next.js Pages API ルート
シグナル: デフォルトエクスポートハンドラーを持つ pages/api/**/*.ts
ルートソース: ファイルシステム規則
メソッドルーティング: ハンドラー内の req.method スイッチ
Fastify
シグナル: fastify.get(), fastify.route(), ルートオプションの schema プロパティ
ルートソース: fastify.register() によるプラグイン登録
スキーマ: Fastify ルートはしばしば JSON Schema を宣言しているため、抽出して変換します
Fastify は、ルートが頻繁に独自のスキーマを宣言するため、最も文書化が容易なフレームワークです。推論する前に、既存の schema.body、schema.response、schema.querystring を優先的に抽出します。
Hono
シグナル: app.get(), app.post(), Hono(), zValidator()
ルートソース: Hono インスタンスのメソッドチェーン
バリデーション: zValidator ミドルウェアを介した zod ベース
zValidator を使用する Hono は、Zod スキーマを直接提供します。Zod --> JSON Schema --> OpenAPI スキーマに変換します。
抽出プロセス
ステップ 1: ルートの発見
プロジェクト内のルート登録をスキャンします。単一のエントリーポイントに依存しないでください。フレームワークはルートを複数のファイルに分割することがよくあります。
# Express: ルーターファイルを見つける
grep -rl "express.Router\|app.get\|app.post\|router\." src/ --include="*.ts" --include="*.js"
# Next.js App Router: ルートハンドラーを見つける
find src/app/api -name "route.ts" -o -name "route.js"
# Next.js Pages: API ルートを見つける
find src/pages/api -name "*.ts" -o -name "*.js"
# Fastify: ルート登録を見つける
grep -rl "fastify\.\(get\|post\|put\|delete\|route\)" src/ --include="*.ts"
# Hono: ルート定義を見つける
grep -rl "app\.\(get\|post\|put\|delete\|patch\)" src/ --include="*.ts"
ステップ 2: スキーマの抽出
各ルートについて、リクエストとレスポンスの形状を特定します。
スキーマソースの優先順位:
- 明示的な Zod/Joi/Yup バリデーションスキーマ(最も信頼性が高い)
- リクエスト/レスポンスに対する TypeScript 型アノテーション
- JSON Schema 宣言(Fastify)
- JSDoc @param / @returns アノテーション
- レスポンス構築からのランタイム推論(最も信頼性が低い -- 概算としてフラグを立てる)
ランタイム推論(オプション 5)を使用する場合、OpenAPI 出力で常にスキーマに x-inferred: true のマークを付け、コンシューマーが不完全である可能性があることを認識できるようにします。
ステップ 3: 認証のトレース
各ルートのミドルウェアチェーンをウォークスルーし、認証要件を決定します:
- 認証ミドルウェアなし:
security: [](公開)としてマーク - Bearer トークンミドルウェア:
security: [{ bearerAuth: [] }]としてマーク - API キーミドルウェア:
security: [{ apiKeyAuth: [] }]としてマーク - セッション/クッキー認証:
security: [{ cookieAuth: [] }]としてマーク - 複数の認証オプション: セキュリティ配列にすべてを代替案としてリストアップ
ステップ 4: エラーのカタログ化
各ハンドラーを読み取り、すべてのエラーレスポンスをリストアップします:
res.status(400).json(...)またはthrow new BadRequestError(...)--> 400 レスポンススキーマres.status(401)--> 401(明示的な throw がなくても認証ミドルウェアが存在する場合に含める)res.status(404)--> 404res.status(409)--> 409(競合、作成操作で一般的)res.status(422)--> 422(バリデーション失敗)res.status(429)--> 429(レート制限、レートリミッターミドルウェアが検出された場合に含める)res.status(500)--> 500(可能性として常に含める)
ステップ 5: 出力の生成
3 つのアーティファクトを生成します:
- OpenAPI 仕様(YAML、JSON ではない -- より読みやすく、差分を取りやすい)
- TypeScript 型(すべてのリクエスト/レスポンス型を含むスタンドアロンの
.d.tsファイル) - curl の例(エンドポイントごとに 1 つ、ヘッダーとサンプルペイロード付き)
決定ポイント
コードベースにバリデーションスキーマがない場合
ハンドラーが Zod/Joi バリデーションなしで生の req.body を受け入れている場合、使用法から型を推論する必要があります。以下のものを探します:
- プロパティアクセスパターン:
req.body.name、req.body.email-->{ name: string, email: string } - 分割代入:
const { name, email } = req.body--> 同じ推論 - データベース挿入呼び出し:
db.users.create({ name: body.name })--> 可能であれば DB スキーマを相互参照
情報レベルで x-schemas-inferred: true の警告で仕様全体にフラグを立てます。
ルートが動的パスセグメントを使用する場合
- Express:
:id--> OpenAPI{id} - Next.js:
[id]--> OpenAPI{id} - Next.js キャッチオール:
[...slug]--> OpenAPI{slug}(配列動作に関する注意付き) - Fastify:
:id--> OpenAPI{id} - Hono:
:id--> OpenAPI{id}
レスポンス形状がステータスコードによって異なる場合
各ステータスコードを独自のスキーマで文書化します。200 と 201 が異なる場合は、それらを 1 つのスキーマにマージしないでください。一般的なパターン:
responses:
'200':
description: ユーザーが見つかりました
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: ユーザーが見つかりません
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
レート制限がエンドポイントごとに異なる場合
OpenAPI 拡張機能を使用してレート制限を文書化します:
x-rate-limit:
requests: 100
window: 60s
scope: per-api-key
レートリミッターがグローバル(アプリレベルで 1 回適用)の場合は、トップレベルの info セクションに文書化します。ルートごとの場合は、各操作に文書化します。
TypeScript 型生成
OpenAPI 仕様と正確に一致する型を生成します。コードベースでブランド型が使用されている場合は、ID にブランド型を使用します。
// OpenAPI 仕様から生成 -- 手動で編集しないでください
export interface CreateUserRequest {
name: string;
email: string;
role?: 'admin' | 'member' | 'viewer';
}
export interface CreateUserResponse {
id: string;
name: string;
email: string;
role: 'admin' | 'member' | 'viewer';
createdAt: string; // ISO 8601
}
export interface ErrorResponse {
error: {
code: string;
message: string;
details?: Array<{
field: string;
issue: string;
}>;
};
}
export interface PaginatedResponse<T> {
data: T[];
meta: {
page: number;
perPage: number;
total: number;
hasMore: boolean;
};
}
Curl 例の生成
エンドポイントごとに 1 つの curl を生成します。現実的だが明らかに偽のデータを使用します。
# GET /api/users/:id -- 単一ユーザーの取得
curl -X GET https://api.example.com/api/users/usr_abc123 \
-H "Authorization: Bearer sk_test_..." \
-H "Accept: application/json"
# POST /api/users -- 新規ユーザーの作成
curl -X POST https://api.example.com/api/users \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"email": "[email protected]",
"role": "member"
}'
# GET /api/users -- ページネーション付きユーザー一覧
curl -X GET "https://api.example.com/api/users?page=1&perPage=20&role=admin" \
-H "Authorization: Bearer sk_test_..." \
-H "Accept: application/json"
curl 例のルール:
- 常に完全な URL を含める(ベースとして
https://api.example.comを使用) - 必要なヘッダーをすべて含める
- リクエストボディにはフォーマットされた JSON で
-dを使用する - クエリパラメータを含む URL は引用符で囲む
- GET でも HTTP メソッドを明示的に表示する
- 認証トークンには
sk_test_...を使用する(明らかに偽) - "string" や "test" ではなく、現実的なフィールド値を使用する
アンチパターン
1. 理想的な API の文書化
症状: 仕様がコードにまだ存在しないエンドポイントを記述している 修正: コードが実際に実装しているもののみを文書化する。計画されたエンドポイントがコメントや仕様ファイルにあってもハンドラーにない場合は、それを除外する。
2. ミドルウェアの副作用の無視
症状: ドキュメントではエンドポイントが公開とされているが、実際には親ミドルウェアを通じて認証が必要である
修正: アプリルートからハンドラーまでの完全なミドルウェアチェーンをトレースする。ルート定義より上の router.use(auth) は、その下のすべてのルートで認証が必要であることを意味する。
3. リクエストボディ形状の推測
症状: バリデーションがないため、req.body を any または object として文書化している
修正: 使用法(プロパティアクセス、分割代入、データベース呼び出し)から推論する。x-inferred: true としてマークする。Zod バリデーションの追加を推奨する。
4. フラットなエラードキュメント
症状: すべてのエンドポイントが詳細なしで同じ汎用的な「400 Bad Request」をリストアップしている 修正: 各ハンドラーのエラーパスを読み取る。返される特定のエラーコードとメッセージを文書化する。異なるバリデーション失敗は異なるサンプルレスポンスを表示する必要がある。
5. 古くなった生成ドキュメント
症状: 仕様が一度生成された後、コードの変更に伴って更新されていない
修正: 既知のパス(docs/openapi.yaml)に生成する。再生成してコミットされた仕様と差分を取る CI チェックを追加する。それらが乖離した場合、ビルドを失敗させる。
6. ページネーションドキュメントの欠落
症状: リストエンドポイントがページネーションのクエリパラメータスキーマなしで文書化されている
修正: ハンドラーが page、limit、cursor、offset、または類似のパラメータをサポートしている場合、デフォルト値と最大値とともに文書化する。
7. 未文書のファイルアップロード
症状: multipart/form-data エンドポイントが JSON として文書化されている
修正: multer、formidable、busboy、またはフレームワークネイティブのファイル処理を検出する。適切なバイナリスキーマで multipart/form-data コンテンツタイプを使用する。
品質チェックリスト
[ ] コードベースのすべてのルートハンドラーに対応する OpenAPI 操作がある
[ ] パスパラメータがコードと仕様で一致している(:id と {userId} の不一致がない)
[ ] リクエストボディスキーマがすべての必須フィールドとオプションフィールドをカバーしている
[ ] レスポンススキーマが実際の JSON 構造と一致している(ハンドラーの戻り値を読んで確認)
[ ] 認証要件がミドルウェアチェーン分析と一致している
[ ] レート制限情報がレート制限ミドルウェアが存在する場所に文書化されている
[ ] エラーレスポンスがハンドラー内の実際の throw/return ステートメントからカタログ化されている
[ ] curl の例が実行中のインスタンスに対して正常に実行される
[ ] TypeScript 型がエラーなくコンパイルされる
[ ] 未文書の x-inferred スキーマがない(フラグが立てられた各スキーマには適切なバリデーションのための TODO がある)
[ ] ページネーションパラメータがデフォルト値と最大値とともに文書化されている
[ ] ファイルアップロードエンドポイントが multipart/form-data コンテンツタイプを使用している
[ ] OpenAPI 仕様が spectral または swagger-cli lint で検証される
[ ] 生成された仕様が CI 差分チェックのために既知のパスにコミットされている
出力アーティファクト
docs/openapi.yaml-- 完全な OpenAPI 3.0/3.1 仕様docs/api-types.d.ts-- すべてのリクエスト/レスポンス形状に対する TypeScript 型定義docs/api-examples.sh-- すべてのエンドポイントに対する実行可能な curl 例docs/api-coverage.md-- 文書化されたルートと文書化されていないルートのレポート
バリデーション
# 生成された OpenAPI 仕様をリント
npx @stoplight/spectral-cli lint docs/openapi.yaml
# 仕様構造を検証
npx swagger-cli validate docs/openapi.yaml
# TypeScript クライアントを生成して型がコンパイルされることを確認
npx openapi-typescript docs/openapi.yaml -o /tmp/api-check.d.ts
tsc --noEmit /tmp/api-check.d.ts
# 最後にコミットされた仕様との差分(CI チェック)
diff <(cat docs/openapi.yaml) <(npx tsx scripts/generate-api-docs.ts --stdout) && echo "仕様は最新です" || echo "仕様が古くなっています"
対象: OpenAPI 生成 | TypeScript 型抽出 | Curl 例作成 | 認証ドキュメント | レート制限ドキュメント | エラーコードカタログ化
併用: api-architect(設計から先に、後で文書化)| openapi-spec-writer(手動作成)| test-automation-expert(生成された仕様に対するコントラクトテスト)