api-docs-generator

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API Docs Generator

API文档生成器

Generate comprehensive, developer-friendly API documentation automatically.
自动生成全面且对开发者友好的API文档。

Core Workflow

核心工作流

  1. Scan routes: Find all API route definitions
  2. Extract schemas: Request/response types, params
  3. Generate docs: Markdown/HTML documentation
  4. Add examples: Request/response examples
  5. Document errors: Error codes and handling
  6. Create guides: Authentication, getting started
  1. 扫描路由:查找所有API路由定义
  2. 提取模式:请求/响应类型、参数
  3. 生成文档:Markdown/HTML格式文档
  4. 添加示例:请求/响应示例
  5. 记录错误:错误码及处理方式
  6. 创建指南:认证、快速入门

Documentation Structure

文档结构

docs/
├── api/
│   ├── index.md              # API overview
│   ├── authentication.md     # Auth guide
│   ├── errors.md             # Error reference
│   ├── rate-limiting.md      # Rate limit info
│   └── endpoints/
│       ├── users.md
│       ├── products.md
│       └── orders.md
├── guides/
│   ├── getting-started.md
│   ├── pagination.md
│   └── webhooks.md
└── sdks/
    ├── javascript.md
    ├── python.md
    └── curl.md
docs/
├── api/
│   ├── index.md              # API概览
│   ├── authentication.md     # 认证指南
│   ├── errors.md             # 错误参考
│   ├── rate-limiting.md      # 限流信息
│   └── endpoints/
│       ├── users.md
│       ├── products.md
│       └── orders.md
├── guides/
│   ├── getting-started.md
│   ├── pagination.md
│   └── webhooks.md
└── sdks/
    ├── javascript.md
    ├── python.md
    └── curl.md

Generator Script

生成器脚本

typescript
// scripts/generate-api-docs.ts
import * as fs from "fs";
import * as path from "path";

interface RouteInfo {
  method: string;
  path: string;
  name: string;
  description?: string;
  params?: ParamInfo[];
  queryParams?: ParamInfo[];
  requestBody?: SchemaInfo;
  responses?: ResponseInfo[];
  auth?: boolean;
  tags?: string[];
}

interface ParamInfo {
  name: string;
  type: string;
  required: boolean;
  description?: string;
  example?: string;
}

interface SchemaInfo {
  type: string;
  properties?: Record<string, PropertyInfo>;
  required?: string[];
  example?: object;
}

interface PropertyInfo {
  type: string;
  description?: string;
  example?: unknown;
  enum?: string[];
  format?: string;
}

interface ResponseInfo {
  status: number;
  description: string;
  schema?: SchemaInfo;
  example?: object;
}

interface DocsOptions {
  title: string;
  baseUrl: string;
  version: string;
  outputDir: string;
  format: "markdown" | "html" | "docusaurus";
}

function generateApiDocs(routes: RouteInfo[], options: DocsOptions): void {
  const { outputDir } = options;

  // Create directories
  fs.mkdirSync(path.join(outputDir, "api", "endpoints"), { recursive: true });
  fs.mkdirSync(path.join(outputDir, "guides"), { recursive: true });

  // Generate overview
  generateOverview(options);

  // Generate auth docs
  generateAuthDocs(options);

  // Generate error docs
  generateErrorDocs(options);

  // Group routes by resource
  const groupedRoutes = groupRoutesByResource(routes);

  // Generate endpoint docs
  for (const [resource, resourceRoutes] of Object.entries(groupedRoutes)) {
    const content = generateEndpointDoc(resource, resourceRoutes, options);
    const filePath = path.join(outputDir, "api", "endpoints", `${resource}.md`);
    fs.writeFileSync(filePath, content);
  }

  // Generate getting started guide
  generateGettingStarted(routes, options);
}

function generateEndpointDoc(
  resource: string,
  routes: RouteInfo[],
  options: DocsOptions
): string {
  const lines: string[] = [];

  // Header
  lines.push(`# ${capitalize(resource)}`);
  lines.push("");
  lines.push(`Endpoints for managing ${resource}.`);
  lines.push("");

  // Table of contents
  lines.push("## Endpoints");
  lines.push("");
  lines.push("| Method | Endpoint | Description |");
  lines.push("|--------|----------|-------------|");

  for (const route of routes) {
    lines.push(
      `| \`${route.method}\` | \`${route.path}\` | ${route.description || route.name} |`
    );
  }
  lines.push("");

  // Detailed documentation for each endpoint
  for (const route of routes) {
    lines.push(generateEndpointSection(route, options));
    lines.push("");
  }

  return lines.join("\n");
}

function generateEndpointSection(
  route: RouteInfo,
  options: DocsOptions
): string {
  const lines: string[] = [];
  const anchor = route.name.toLowerCase().replace(/\s+/g, "-");

  // Endpoint header
  lines.push(`## ${route.name} {#${anchor}}`);
  lines.push("");
  lines.push(
    `<span class="method method-${route.method.toLowerCase()}">${route.method}</span> \`${route.path}\``
  );
  lines.push("");

  if (route.description) {
    lines.push(route.description);
    lines.push("");
  }

  // Authentication
  if (route.auth) {
    lines.push("### Authentication");
    lines.push("");
    lines.push("This endpoint requires authentication. Include the Bearer token in the Authorization header.");
    lines.push("");
  }

  // Path parameters
  if (route.params?.length) {
    lines.push("### Path Parameters");
    lines.push("");
    lines.push("| Parameter | Type | Required | Description |");
    lines.push("|-----------|------|----------|-------------|");

    for (const param of route.params) {
      lines.push(
        `| \`${param.name}\` | ${param.type} | ${param.required ? "Yes" : "No"} | ${param.description || "-"} |`
      );
    }
    lines.push("");
  }

  // Query parameters
  if (route.queryParams?.length) {
    lines.push("### Query Parameters");
    lines.push("");
    lines.push("| Parameter | Type | Required | Default | Description |");
    lines.push("|-----------|------|----------|---------|-------------|");

    for (const param of route.queryParams) {
      lines.push(
        `| \`${param.name}\` | ${param.type} | ${param.required ? "Yes" : "No"} | ${param.example || "-"} | ${param.description || "-"} |`
      );
    }
    lines.push("");
  }

  // Request body
  if (route.requestBody) {
    lines.push("### Request Body");
    lines.push("");
    lines.push("```json");
    lines.push(JSON.stringify(route.requestBody.example || {}, null, 2));
    lines.push("```");
    lines.push("");

    if (route.requestBody.properties) {
      lines.push("| Field | Type | Required | Description |");
      lines.push("|-------|------|----------|-------------|");

      for (const [name, prop] of Object.entries(route.requestBody.properties)) {
        const required = route.requestBody.required?.includes(name)
          ? "Yes"
          : "No";
        lines.push(
          `| \`${name}\` | ${prop.type} | ${required} | ${prop.description || "-"} |`
        );
      }
      lines.push("");
    }
  }

  // Responses
  lines.push("### Responses");
  lines.push("");

  const responses = route.responses || [
    { status: 200, description: "Successful response" },
    { status: 400, description: "Bad request" },
    { status: 401, description: "Unauthorized" },
    { status: 404, description: "Not found" },
  ];

  for (const response of responses) {
    lines.push(`#### ${response.status} ${response.description}`);
    lines.push("");

    if (response.example) {
      lines.push("```json");
      lines.push(JSON.stringify(response.example, null, 2));
      lines.push("```");
      lines.push("");
    }
  }

  // Example request
  lines.push("### Example Request");
  lines.push("");
  lines.push("```bash");
  lines.push(generateCurlExample(route, options));
  lines.push("```");
  lines.push("");

  return lines.join("\n");
}

function generateCurlExample(route: RouteInfo, options: DocsOptions): string {
  const parts: string[] = ["curl"];
  parts.push(`-X ${route.method}`);

  let url = `${options.baseUrl}${route.path}`;
  url = url.replace(/:(\w+)/g, "{$1}");
  parts.push(`"${url}"`);

  if (["POST", "PUT", "PATCH"].includes(route.method)) {
    parts.push('-H "Content-Type: application/json"');
  }

  if (route.auth) {
    parts.push('-H "Authorization: Bearer YOUR_TOKEN"');
  }

  if (route.requestBody?.example) {
    parts.push(`-d '${JSON.stringify(route.requestBody.example)}'`);
  }

  return parts.join(" \\\n  ");
}

function generateOverview(options: DocsOptions): void {
  const content = `# ${options.title} API Reference

Version: ${options.version}

Base URL: \`${options.baseUrl}\`
typescript
// scripts/generate-api-docs.ts
import * as fs from "fs";
import * as path from "path";

interface RouteInfo {
  method: string;
  path: string;
  name: string;
  description?: string;
  params?: ParamInfo[];
  queryParams?: ParamInfo[];
  requestBody?: SchemaInfo;
  responses?: ResponseInfo[];
  auth?: boolean;
  tags?: string[];
}

interface ParamInfo {
  name: string;
  type: string;
  required: boolean;
  description?: string;
  example?: string;
}

interface SchemaInfo {
  type: string;
  properties?: Record<string, PropertyInfo>;
  required?: string[];
  example?: object;
}

interface PropertyInfo {
  type: string;
  description?: string;
  example?: unknown;
  enum?: string[];
  format?: string;
}

interface ResponseInfo {
  status: number;
  description: string;
  schema?: SchemaInfo;
  example?: object;
}

interface DocsOptions {
  title: string;
  baseUrl: string;
  version: string;
  outputDir: string;
  format: "markdown" | "html" | "docusaurus";
}

function generateApiDocs(routes: RouteInfo[], options: DocsOptions): void {
  const { outputDir } = options;

  // 创建目录
  fs.mkdirSync(path.join(outputDir, "api", "endpoints"), { recursive: true });
  fs.mkdirSync(path.join(outputDir, "guides"), { recursive: true });

  // 生成概览文档
  generateOverview(options);

  // 生成认证文档
  generateAuthDocs(options);

  // 生成错误文档
  generateErrorDocs(options);

  // 按资源分组路由
  const groupedRoutes = groupRoutesByResource(routes);

  // 生成端点文档
  for (const [resource, resourceRoutes] of Object.entries(groupedRoutes)) {
    const content = generateEndpointDoc(resource, resourceRoutes, options);
    const filePath = path.join(outputDir, "api", "endpoints", `${resource}.md`);
    fs.writeFileSync(filePath, content);
  }

  // 生成快速入门指南
  generateGettingStarted(routes, options);
}

function generateEndpointDoc(
  resource: string,
  routes: RouteInfo[],
  options: DocsOptions
): string {
  const lines: string[] = [];

  // 标题
  lines.push(`# ${capitalize(resource)}`);
  lines.push("");
  lines.push(`用于管理${resource}的端点。`);
  lines.push("");

  // 目录
  lines.push("## 端点列表");
  lines.push("");
  lines.push("| 请求方法 | 端点路径 | 描述 |");
  lines.push("|--------|----------|-------------|");

  for (const route of routes) {
    lines.push(
      `| \`${route.method}\` | \`${route.path}\` | ${route.description || route.name} |`
    );
  }
  lines.push("");

  // 每个端点的详细文档
  for (const route of routes) {
    lines.push(generateEndpointSection(route, options));
    lines.push("");
  }

  return lines.join("\n");
}

function generateEndpointSection(
  route: RouteInfo,
  options: DocsOptions
): string {
  const lines: string[] = [];
  const anchor = route.name.toLowerCase().replace(/\s+/g, "-");

  // 端点标题
  lines.push(`## ${route.name} {#${anchor}}`);
  lines.push("");
  lines.push(
    `<span class="method method-${route.method.toLowerCase()}">${route.method}</span> \`${route.path}\``
  );
  lines.push("");

  if (route.description) {
    lines.push(route.description);
    lines.push("");
  }

  // 认证说明
  if (route.auth) {
    lines.push("### 认证要求");
    lines.push("");
    lines.push("该端点需要认证,请在Authorization请求头中携带Bearer令牌。");
    lines.push("");
  }

  // 路径参数
  if (route.params?.length) {
    lines.push("### 路径参数");
    lines.push("");
    lines.push("| 参数名 | 类型 | 是否必填 | 描述 |");
    lines.push("|-----------|------|----------|-------------|");

    for (const param of route.params) {
      lines.push(
        `| \`${param.name}\` | ${param.type} | ${param.required ? "是" : "否"} | ${param.description || "-"} |`
      );
    }
    lines.push("");
  }

  // 查询参数
  if (route.queryParams?.length) {
    lines.push("### 查询参数");
    lines.push("");
    lines.push("| 参数名 | 类型 | 是否必填 | 默认值 | 描述 |");
    lines.push("|-----------|------|----------|---------|-------------|");

    for (const param of route.queryParams) {
      lines.push(
        `| \`${param.name}\` | ${param.type} | ${param.required ? "是" : "否"} | ${param.example || "-"} | ${param.description || "-"} |`
      );
    }
    lines.push("");
  }

  // 请求体
  if (route.requestBody) {
    lines.push("### 请求体");
    lines.push("");
    lines.push("```json");
    lines.push(JSON.stringify(route.requestBody.example || {}, null, 2));
    lines.push("```");
    lines.push("");

    if (route.requestBody.properties) {
      lines.push("| 字段名 | 类型 | 是否必填 | 描述 |");
      lines.push("|-------|------|----------|-------------|");

      for (const [name, prop] of Object.entries(route.requestBody.properties)) {
        const required = route.requestBody.required?.includes(name)
          ? "是"
          : "否";
        lines.push(
          `| \`${name}\` | ${prop.type} | ${required} | ${prop.description || "-"} |`
        );
      }
      lines.push("");
    }
  }

  // 响应示例
  lines.push("### 响应结果");
  lines.push("");

  const responses = route.responses || [
    { status: 200, description: "请求成功" },
    { status: 400, description: "请求参数错误" },
    { status: 401, description: "未授权访问" },
    { status: 404, description: "资源不存在" },
  ];

  for (const response of responses) {
    lines.push(`#### ${response.status} ${response.description}`);
    lines.push("");

    if (response.example) {
      lines.push("```json");
      lines.push(JSON.stringify(response.example, null, 2));
      lines.push("```");
      lines.push("");
    }
  }

  // 请求示例
  lines.push("### 请求示例");
  lines.push("");
  lines.push("```bash");
  lines.push(generateCurlExample(route, options));
  lines.push("```");
  lines.push("");

  return lines.join("\n");
}

function generateCurlExample(route: RouteInfo, options: DocsOptions): string {
  const parts: string[] = ["curl"];
  parts.push(`-X ${route.method}`);

  let url = `${options.baseUrl}${route.path}`;
  url = url.replace(/:(\w+)/g, "{$1}");
  parts.push(`"${url}"`);

  if (["POST", "PUT", "PATCH"].includes(route.method)) {
    parts.push('-H "Content-Type: application/json"');
  }

  if (route.auth) {
    parts.push('-H "Authorization: Bearer YOUR_TOKEN"');
  }

  if (route.requestBody?.example) {
    parts.push(`-d '${JSON.stringify(route.requestBody.example)}'`);
  }

  return parts.join(" \\\n  ");
}

function generateOverview(options: DocsOptions): void {
  const content = `# ${options.title} API参考手册

版本:${options.version}

基础URL:\`${options.baseUrl}\`

Overview

概览

Welcome to the ${options.title} API documentation. This API provides programmatic access to [describe your service].
欢迎使用${options.title} API文档。本API提供对[请描述你的服务]的程序化访问能力。

Quick Links

快速链接

  • Authentication
  • Error Handling
  • Rate Limiting
  • 认证指南
  • 错误处理
  • 限流说明

Endpoints

端点资源

ResourceDescription
UsersUser management
ProductsProduct catalog
OrdersOrder processing
资源描述
用户用户管理相关端点
商品商品目录相关端点
订单订单处理相关端点

SDKs & Libraries

SDK与工具库

  • JavaScript/TypeScript
  • Python
  • cURL Examples
  • JavaScript/TypeScript
  • Python
  • cURL示例

Support

支持与帮助

If you have questions or need help, please:
  • Check the FAQ
  • Open an issue on GitHub
  • Contact support@example.com `;
    fs.writeFileSync(path.join(options.outputDir, "api", "index.md"), content); }
function generateAuthDocs(options: DocsOptions): void { const content = `# Authentication
The ${options.title} API uses Bearer token authentication.
如果有问题或需要帮助,请:
  • 查看常见问题
  • 在GitHub上提交Issue
  • 联系support@example.com `;
    fs.writeFileSync(path.join(options.outputDir, "api", "index.md"), content); }
function generateAuthDocs(options: DocsOptions): void { const content = `# 认证指南
${options.title} API采用Bearer令牌认证机制。

Getting an Access Token

获取访问令牌

Login

登录获取

```bash curl -X POST "${options.baseUrl}/auth/login" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "your-password"}' ```
Response:
```json { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expiresIn": 3600, "tokenType": "Bearer" } ```
```bash curl -X POST "${options.baseUrl}/auth/login" \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "your-password"}' ```
响应结果:
```json { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "expiresIn": 3600, "tokenType": "Bearer" } ```

Using the Token

使用令牌

Include the token in the Authorization header of all authenticated requests:
```bash curl -X GET "${options.baseUrl}/users" \ -H "Authorization: Bearer YOUR_TOKEN" ```
在所有需要认证的请求头中包含Authorization令牌:
```bash curl -X GET "${options.baseUrl}/users" \ -H "Authorization: Bearer YOUR_TOKEN" ```

Token Expiration

令牌过期

Tokens expire after 1 hour. When a token expires, you'll receive a 401 response:
```json { "error": { "code": "TOKEN_EXPIRED", "message": "Your access token has expired" } } ```
Refresh your token using the refresh endpoint:
```bash curl -X POST "${options.baseUrl}/auth/refresh" \ -H "Content-Type: application/json" \ -d '{"refreshToken": "YOUR_REFRESH_TOKEN"}' ```
令牌有效期为1小时。令牌过期时,你会收到401状态码响应:
```json { "error": { "code": "TOKEN_EXPIRED", "message": "你的访问令牌已过期" } } ```
通过刷新令牌端点获取新令牌:
```bash curl -X POST "${options.baseUrl}/auth/refresh" \ -H "Content-Type: application/json" \ -d '{"refreshToken": "YOUR_REFRESH_TOKEN"}' ```

API Keys

API密钥

For server-to-server communication, you can use API keys:
```bash curl -X GET "${options.baseUrl}/users" \ -H "X-API-Key: YOUR_API_KEY" ```
Generate API keys in your dashboard under Settings > API Keys. `;
fs.writeFileSync( path.join(options.outputDir, "api", "authentication.md"), content ); }
function generateErrorDocs(options: DocsOptions): void { const content = `# Error Handling
The API uses conventional HTTP status codes and returns errors in a consistent format.
对于服务器到服务器的通信,你可以使用API密钥:
```bash curl -X GET "${options.baseUrl}/users" \ -H "X-API-Key: YOUR_API_KEY" ```
在你的控制台中,进入设置>API密钥页面生成API密钥。 `;
fs.writeFileSync( path.join(options.outputDir, "api", "authentication.md"), content ); }
function generateErrorDocs(options: DocsOptions): void { const content = `# 错误处理
API采用标准HTTP状态码,并返回格式统一的错误信息。

Error Response Format

错误响应格式

```json { "success": false, "error": { "code": "ERROR_CODE", "message": "Human-readable error message", "details": { "field": ["Specific error for this field"] }, "trace_id": "abc123" } } ```
```json { "success": false, "error": { "code": "ERROR_CODE", "message": "易读的错误提示信息", "details": { "field": ["该字段的具体错误信息"] }, "trace_id": "abc123" } } ```

HTTP Status Codes

HTTP状态码说明

CodeDescription
200OK - Request succeeded
201Created - Resource created successfully
204No Content - Request succeeded, no content returned
400Bad Request - Invalid request data
401Unauthorized - Missing or invalid authentication
403Forbidden - Insufficient permissions
404Not Found - Resource doesn't exist
409Conflict - Resource already exists
422Unprocessable Entity - Validation error
429Too Many Requests - Rate limit exceeded
500Internal Server Error - Server error
状态码描述
200成功 - 请求已处理完成
201创建成功 - 资源已成功创建
204无内容 - 请求成功,但无返回数据
400请求错误 - 请求数据无效
401未授权 - 缺少或无效的认证信息
403禁止访问 - 权限不足
404未找到 - 资源不存在
409冲突 - 资源已存在
422处理失败 - 数据验证错误
429请求频繁 - 超出限流限制
500服务器错误 - 服务器内部故障

Error Codes

错误码说明

Validation Errors

验证错误

CodeDescription
`VALIDATION_ERROR`Request body validation failed
`INVALID_FORMAT`Field format is invalid
`REQUIRED_FIELD`Required field is missing
错误码描述
`VALIDATION_ERROR`请求体验证失败
`INVALID_FORMAT`字段格式无效
`REQUIRED_FIELD`必填字段缺失

Authentication Errors

认证错误

CodeDescription
`UNAUTHORIZED`No authentication provided
`INVALID_TOKEN`Token is invalid or malformed
`TOKEN_EXPIRED`Token has expired
`INSUFFICIENT_PERMISSIONS`User lacks required permissions
错误码描述
`UNAUTHORIZED`未提供认证信息
`INVALID_TOKEN`令牌无效或格式错误
`TOKEN_EXPIRED`令牌已过期
`INSUFFICIENT_PERMISSIONS`用户权限不足

Resource Errors

资源相关错误

CodeDescription
`NOT_FOUND`Resource doesn't exist
`ALREADY_EXISTS`Resource already exists
`CONFLICT`Operation conflicts with current state
错误码描述
`NOT_FOUND`资源不存在
`ALREADY_EXISTS`资源已存在
`CONFLICT`操作与当前资源状态冲突

Rate Limiting

限流错误

CodeDescription
`RATE_LIMIT_EXCEEDED`Too many requests
When rate limited, check the response headers:
``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1640000000 ```
错误码描述
`RATE_LIMIT_EXCEEDED`请求次数过多
当触发限流时,可查看响应头获取详细信息:
``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 1640000000 ```

Handling Errors

错误处理示例

```typescript try { const response = await api.get('/users'); } catch (error) { if (error.response) { switch (error.response.status) { case 401: // Redirect to login break; case 403: // Show permission denied break; case 404: // Show not found break; case 429: // Implement retry with backoff break; default: // Show generic error } } } ``` `;
fs.writeFileSync(path.join(options.outputDir, "api", "errors.md"), content); }
function generateGettingStarted( routes: RouteInfo[], options: DocsOptions ): void { const content = `# Getting Started
This guide will help you make your first API request.
```typescript try { const response = await api.get('/users'); } catch (error) { if (error.response) { switch (error.response.status) { case 401: // 跳转到登录页面 break; case 403: // 显示权限不足提示 break; case 404: // 显示资源不存在提示 break; case 429: // 实现退避重试机制 break; default: // 显示通用错误提示 } } } ``` `;
fs.writeFileSync(path.join(options.outputDir, "api", "errors.md"), content); }
function generateGettingStarted( routes: RouteInfo[], options: DocsOptions ): void { const content = `# 快速入门
本指南将帮助你完成首次API请求。

Prerequisites

前置条件

  • An API key or user account
  • A tool to make HTTP requests (curl, Postman, or your preferred HTTP client)
  • API密钥或用户账号
  • HTTP请求工具(如curl、Postman或你偏好的HTTP客户端)

Step 1: Get Your API Credentials

步骤1:获取API凭证

  1. Sign up for an account at example.com
  2. Navigate to Settings > API Keys
  3. Generate a new API key
  1. example.com注册账号
  2. 进入设置>API密钥页面
  3. 生成新的API密钥

Step 2: Make Your First Request

步骤2:发起首次请求

Let's fetch a list of users:
```bash curl -X GET "${options.baseUrl}/users" \ -H "Authorization: Bearer YOUR_TOKEN" ```
You should receive a response like:
```json { "success": true, "data": [ { "id": "user_123", "name": "John Doe", "email": "john@example.com" } ], "meta": { "page": 1, "limit": 10, "total": 1 } } ```
我们来获取用户列表:
```bash curl -X GET "${options.baseUrl}/users" \ -H "Authorization: Bearer YOUR_TOKEN" ```
你会收到如下响应:
```json { "success": true, "data": [ { "id": "user_123", "name": "John Doe", "email": "john@example.com" } ], "meta": { "page": 1, "limit": 10, "total": 1 } } ```

Step 3: Create a Resource

步骤3:创建资源

```bash curl -X POST "${options.baseUrl}/users" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "name": "Jane Doe", "email": "jane@example.com" }' ```
```bash curl -X POST "${options.baseUrl}/users" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "name": "Jane Doe", "email": "jane@example.com" }' ```

Next Steps

下一步

  • Read the Authentication Guide
  • Explore the API Reference
  • Check out Error Handling
  • Try the Postman Collection `;
    fs.writeFileSync( path.join(options.outputDir, "guides", "getting-started.md"), content ); }
function groupRoutesByResource( routes: RouteInfo[] ): Record<string, RouteInfo[]> { const groups: Record<string, RouteInfo[]> = {};
for (const route of routes) { const parts = route.path.split("/").filter(Boolean); const resource = parts[0] || "api";
if (!groups[resource]) {
  groups[resource] = [];
}
groups[resource].push(route);
}
return groups; }
function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); }
undefined
  • 阅读认证指南
  • 浏览API参考手册
  • 查看错误处理
  • 尝试Postman集合 `;
    fs.writeFileSync( path.join(options.outputDir, "guides", "getting-started.md"), content ); }
function groupRoutesByResource( routes: RouteInfo[] ): Record<string, RouteInfo[]> { const groups: Record<string, RouteInfo[]> = {};
for (const route of routes) { const parts = route.path.split("/").filter(Boolean); const resource = parts[0] || "api";
if (!groups[resource]) {
  groups[resource] = [];
}
groups[resource].push(route);
}
return groups; }
function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); }
undefined

Example Generated Documentation

生成的文档示例

users.md

users.md

markdown
undefined
markdown
undefined

Users

用户

Endpoints for managing users.
用于管理用户的端点。

Endpoints

端点列表

MethodEndpointDescription
GET
/api/users
List all users
GET
/api/users/:id
Get user by ID
POST
/api/users
Create new user
PUT
/api/users/:id
Update user
DELETE
/api/users/:id
Delete user
请求方法端点路径描述
GET
/api/users
获取所有用户列表
GET
/api/users/:id
根据ID获取用户详情
POST
/api/users
创建新用户
PUT
/api/users/:id
更新用户信息
DELETE
/api/users/:id
删除用户

List Users {#list-users}

获取用户列表 {#list-users}

<span class="method method-get">GET</span>
/api/users
Retrieve a paginated list of users.
<span class="method method-get">GET</span>
/api/users
获取分页的用户列表。

Authentication

认证要求

This endpoint requires authentication. Include the Bearer token in the Authorization header.
该端点需要认证,请在Authorization请求头中携带Bearer令牌。

Query Parameters

查询参数

ParameterTypeRequiredDefaultDescription
page
integerNo1Page number
limit
integerNo10Items per page (max 100)
sort
stringNo-Sort field
order
stringNodescSort order (asc/desc)
参数名类型是否必填默认值描述
page
integer1页码
limit
integer10每页数量(最大100)
sort
string-排序字段
order
stringdesc排序顺序(升序/降序)

Responses

响应结果

200 OK

200 请求成功

json
{
  "success": true,
  "data": [
    {
      "id": "user_abc123",
      "name": "John Doe",
      "email": "john@example.com",
      "role": "user",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 156,
    "total_pages": 16
  }
}
json
{
  "success": true,
  "data": [
    {
      "id": "user_abc123",
      "name": "John Doe",
      "email": "john@example.com",
      "role": "user",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 156,
    "total_pages": 16
  }
}

401 Unauthorized

401 未授权

json
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required"
  }
}
json
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "需要认证信息"
  }
}

Example Request

请求示例

bash
curl -X GET "https://api.example.com/users?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN"
bash
curl -X GET "https://api.example.com/users?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN"

Create User {#create-user}

创建用户 {#create-user}

<span class="method method-post">POST</span>
/api/users
Create a new user account.
<span class="method method-post">POST</span>
/api/users
创建新用户账号。

Authentication

认证要求

This endpoint requires authentication. Include the Bearer token in the Authorization header.
该端点需要认证,请在Authorization请求头中携带Bearer令牌。

Request Body

请求体

json
{
  "name": "John Doe",
  "email": "john@example.com",
  "role": "user"
}
FieldTypeRequiredDescription
name
stringYesUser's full name
email
stringYesUser's email (must be unique)
role
stringNoUser role (user, admin)
json
{
  "name": "John Doe",
  "email": "john@example.com",
  "role": "user"
}
字段名类型是否必填描述
name
string用户全名
email
string用户邮箱(需唯一)
role
string用户角色(user, admin)

Responses

响应结果

201 Created

201 创建成功

json
{
  "success": true,
  "data": {
    "id": "user_xyz789",
    "name": "John Doe",
    "email": "john@example.com",
    "role": "user",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}
json
{
  "success": true,
  "data": {
    "id": "user_xyz789",
    "name": "John Doe",
    "email": "john@example.com",
    "role": "user",
    "createdAt": "2024-01-15T10:30:00Z"
  }
}

400 Bad Request

400 请求错误

json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request data",
    "details": {
      "email": ["Invalid email format"]
    }
  }
}
json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "请求数据无效",
    "details": {
      "email": ["邮箱格式无效"]
    }
  }
}

Example Request

请求示例

bash
curl -X POST "https://api.example.com/users" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"name": "John Doe", "email": "john@example.com"}'
undefined
bash
curl -X POST "https://api.example.com/users" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{"name": "John Doe", "email": "john@example.com"}'
undefined

CLI Script

CLI脚本

typescript
#!/usr/bin/env node
// scripts/docs-gen.ts
import * as fs from "fs";
import { program } from "commander";

program
  .name("docs-gen")
  .description("Generate API documentation from routes")
  .option("-f, --framework <type>", "Framework (express|nextjs|fastify)", "express")
  .option("-s, --source <path>", "Source directory", "./src")
  .option("-o, --output <path>", "Output directory", "./docs")
  .option("-t, --title <name>", "API title", "My API")
  .option("-v, --version <version>", "API version", "1.0.0")
  .option("-b, --base-url <url>", "Base URL", "https://api.example.com")
  .option("--format <type>", "Output format (markdown|html|docusaurus)", "markdown")
  .parse();

const options = program.opts();

async function main() {
  const routes = await scanRoutes(options.framework, options.source);

  generateApiDocs(routes, {
    title: options.title,
    baseUrl: options.baseUrl,
    version: options.version,
    outputDir: options.output,
    format: options.format,
  });

  console.log(`Generated documentation in ${options.output}`);
}

main();
typescript
#!/usr/bin/env node
// scripts/docs-gen.ts
import * as fs from "fs";
import { program } from "commander";

program
  .name("docs-gen")
  .description("从路由生成API文档")
  .option("-f, --framework <type>", "框架类型(express|nextjs|fastify)", "express")
  .option("-s, --source <path>", "源码目录", "./src")
  .option("-o, --output <path>", "输出目录", "./docs")
  .option("-t, --title <name>", "API标题", "My API")
  .option("-v, --version <version>", "API版本", "1.0.0")
  .option("-b, --base-url <url>", "基础URL", "https://api.example.com")
  .option("--format <type>", "输出格式(markdown|html|docusaurus)", "markdown")
  .parse();

const options = program.opts();

async function main() {
  const routes = await scanRoutes(options.framework, options.source);

  generateApiDocs(routes, {
    title: options.title,
    baseUrl: options.baseUrl,
    version: options.version,
    outputDir: options.output,
    format: options.format,
  });

  console.log(`文档已生成至${options.output}目录`);
}

main();

Best Practices

最佳实践

  1. Keep docs updated: Regenerate docs on route changes
  2. Include examples: Show real request/response examples
  3. Document errors: List all possible error codes
  4. Add authentication guide: Explain how to authenticate
  5. Use consistent format: Follow same structure for all endpoints
  6. Version your docs: Match doc versions to API versions
  7. Make it searchable: Include table of contents and anchors
  8. Provide SDKs: Link to client libraries and code examples
  1. 保持文档更新:路由变更时重新生成文档
  2. 添加示例:展示真实的请求/响应示例
  3. 记录错误:列出所有可能的错误码
  4. 完善认证指南:详细说明认证流程
  5. 格式统一:所有端点遵循相同的文档结构
  6. 版本化文档:文档版本与API版本保持一致
  7. 支持搜索:包含目录和锚点
  8. 提供SDK:链接到客户端库和代码示例

Output Checklist

输出检查清单

  • API overview with quick links
  • Authentication guide
  • Error handling reference
  • Endpoint documentation per resource
  • Path and query parameters documented
  • Request body schemas with field descriptions
  • Response examples for all status codes
  • cURL examples for each endpoint
  • Getting started guide
  • SDK/library examples
  • 包含快速链接的API概览文档
  • 认证指南文档
  • 错误处理参考文档
  • 按资源分类的端点文档
  • 路径和查询参数说明
  • 带字段描述的请求体模式
  • 所有状态码的响应示例
  • 每个端点的cURL请求示例
  • 快速入门指南
  • SDK/工具库示例文档