# Hono OpenAPI规范

## 常见不规范问题
1. **路径参数问题**:
   - ❌ 使用冒号定义路径参数: `/:id`
   - ✅ 必须使用花括号: `/{id}`
     
2. **参数Schema缺失**:
   - ❌ 未定义params Schema
   - ✅ 必须定义并添加OpenAPI元数据

3. **参数获取方式**:
   - ❌ 使用`c.req.param()`
   - ✅ 必须使用`c.req.valid('param')`

4. **URL参数类型转换**:
   - ❌ 直接使用z.number()验证URL查询参数
   - ✅ 必须使用z.coerce.number<number>()自动转换字符串参数, zod v4必须要加 <number>

5. **OpenAPI元数据**:
   - ❌ 路径参数缺少OpenAPI描述
   - ✅ 必须包含example和description

6. **api响应**:
   - ❌ 200响应码缺少
   - ✅ 200也必须写，c.json(result, 200)

7. **认证中间件**:
   - ❌ security: [{ Bearer: [] }],
   - ✅ middleware: [authMiddleware],

8. **子路由路径**:
   - ❌ path: '/users',
   - ✅ path: '/',
   - ❌ path: '/users/{id}',
   - ✅ path: '/{id}',

## 核心规范
### 1. 路由定义

### 2. 查询参数处理
- **URL参数类型**:
  - URL查询参数总是以字符串形式传递
  - 必须正确处理字符串到其他类型的转换
- **数字参数处理**:
  ```typescript
  // 错误方式 - 直接使用z.number()
  z.number().int().positive() // 无法处理字符串参数

  // 正确方式 - 使用z.coerce.number()
  z.coerce.number().int().positive() // 自动转换字符串参数
  ```
- **布尔参数处理**:
  ```typescript
  // 错误方式 - 直接使用z.boolean()
  z.boolean() // 无法处理字符串参数

  // 正确方式 - 使用z.coerce.boolean()
  z.coerce.boolean() // 自动转换字符串参数
  ```
- **路径参数**:
  - 必须使用花括号 `{}` 定义 (例: `/{id}`)
  - 必须定义 params Schema 并添加 OpenAPI 元数据:
    ```typescript
    const GetParams = z.object({
      id: z.string().openapi({
        param: { name: 'id', in: 'path' },
        example: '1',
        description: '资源ID'
      })
    });
    ```
  - 路由定义中必须包含 params 定义:
    ```typescript
    request: { params: GetParams }
    ```
  - 必须使用 `c.req.valid('param')` 获取路径参数

- **请求定义**:
  ```typescript
  request: {
    body: {
      content: {
        'application/json': { schema: YourZodSchema }
      }
    }
  }
  ```

- **响应定义**:
  ```typescript
  responses: {
    200: {
      description: '成功响应描述',
      content: { 'application/json': { schema: SuccessSchema } }
    },
    400: {
      description: '客户端错误',
      content: { 'application/json': { schema: ErrorSchema } }
    },
    500: {
      description: '服务器错误',
      content: { 'application/json': { schema: ErrorSchema } }
    }
  }
  ```
  列表响应定义示例
  ```typescript
  // 列表响应Schema, 响应时，data应统一用实体中定义的schema
  import { RackInfoSchema } from '@/server/modules/racks/rack-info.entity';
  const RackListResponse = z.object({
    data: z.array(RackInfoSchema),
    pagination: z.object({
      total: z.number().openapi({
        example: 100,
        description: '总记录数'
      }),
      current: z.number().openapi({
        example: 1,
        description: '当前页码'
      }),
      pageSize: z.number().openapi({
        example: 10,
        description: '每页数量'
      })
    })
  });
  ```

- **路由示例**:
  ```typescript
  const routeDef = createRoute({
    method: 'post',
    path: '/',
    middleware: [authMiddleware],
    request: {
      body: {
        content: { 'application/json': { schema: CreateSchema } }
      }
    },
    responses: {
      200: { ... },
      400: { ... },
      500: { ... }
    }
  });
  ```

### 2. 错误处理
- 错误响应必须使用统一格式: `{ code: number, message: string }`
- 必须与OpenAPI定义完全一致
- 处理示例:
  ```typescript
  try {
    // 业务逻辑
  } catch (error) {
    return c.json({ code: 500, message: '操作失败' }, 500);
  }
  ```

### 3. dataSource引入
- 示例:
  ```typescript
  import { AppDataSource } from '@/server/data-source';
  ```

### 4. service初始化
- 示例:
  ```typescript
  import { WorkspaceService } from '@/server/modules/workspaces/workspace.service';
  const workspaceService = new WorkspaceService(AppDataSource);

### 5. 用户context获取
- 示例:
  ```typescript
  const user = c.get('user');
  ```
  - 注意: 确保 `c.get('user')` 已经在 `authMiddleware` 中设置

### 6. AuthContext引用
- 示例:
  ```typescript
  import { AuthContext } from '@/server/types/context';
  ```

### 7. createRoute, OpenAPIHono 引入
- 示例:
  ```typescript
  import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
  ```

### 8. ErrorSchema 引入
- 示例:
  ```typescript
  import { ErrorSchema } from '@/server/utils/errorHandler';
  ```

## 进阶规范
### 1. 路由聚合
当多个相关路由需要组合时:
1. **文件结构**:
   - 拆分为独立文件 (`create.ts`, `list.ts` 等)
   - 创建 `index.ts` 聚合所有子路由

  ```
  src/server/api/
  ├── [resource]/          # 资源路由目录
  │   ├── [id]/           # 带ID的子路由
  │   │   ├── get.ts      # 获取单条
  │   │   ├── put.ts      # 更新单条  
  │   │   └── delete.ts   # 删除单条
  │   ├── get.ts          # 列表查询
  │   ├── post.ts         # 创建资源
  │   └── index.ts        # 聚合导出
  ```

2. **实现**:
   ```typescript   
    import listRoute from './get';
    import createRackRoute from './post';
    import getByIdRoute from './[id]/get';
    import updateRoute from './[id]/put';
    import deleteRoute from './[id]/delete';
    import { OpenAPIHono } from '@hono/zod-openapi';

    const app = new OpenAPIHono()
      .route('/', listRoute)
      .route('/', createRackRoute)
      .route('/', getByIdRoute)
      .route('/', updateRoute)
      .route('/', deleteRoute)

    export default app;
   ```

3. **优势**:
   - 保持模块化
   - 简化维护
   - 统一API入口

## 路由文件代码结构规范
  +imports: 依赖导入
  +serviceInit: 服务初始化
  +paramsSchema: 路径参数定义
  +responseSchema: 响应定义
  +errorSchema: 错误定义
  +routeDef: 路由定义
  +app: 路由实例

## src/server/api.ts 统一引入
```ts
import authRoute from '@/server/api/auth/index'
const routes = api.route('/api/v1/auth', authRoute)
```

## 完整示例
```typescript
// 路由实例
const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
  try {
    // 业务逻辑
    return c.json(result, 200);
  } catch (error) {
    return c.json({ 
      code: 500, 
      message: error instanceOf Error ? error.message : '操作失败' 
    }, 500);
  }
});

export default app;
```