- 重构项目结构:controllers/services -> modules模块化组织 - 新增Drizzle ORM集成和数据库schema定义 - 添加完整的开发规范文档(.cursor/rules/) - 重新组织插件结构为子目录方式 - 新增用户模块和示例代码 - 更新类型定义并移除试验性代码 - 添加API文档和JWT使用示例 关联任务计划文档
175 lines
5.0 KiB
Markdown
175 lines
5.0 KiB
Markdown
# API 开发规范
|
||
|
||
## 文件结构
|
||
|
||
每个API模块必须包含以下文件:
|
||
|
||
- `*.schema.ts` - 请求参数和数据结构定义 + TypeScript类型导出
|
||
- `*.response.ts` - 响应格式定义 + 响应类型导出
|
||
- `*.service.ts` - 业务逻辑实现(使用类型注解)
|
||
- `*.controller.ts` - 路由和控制器(使用Schema验证)
|
||
- `*.test.ts` - 测试用例(类型安全的测试数据)
|
||
|
||
## 开发流程
|
||
|
||
1. **Schema 定义** - 使用 TypeBox 定义请求参数和数据结构,导出TypeScript类型
|
||
2. **Response 定义** - 基于全局响应格式定义各种场景的响应,导出响应类型
|
||
3. **Service 实现** - 编写业务逻辑,使用类型注解确保类型安全
|
||
4. **Controller 实现** - 集成JWT认证、Schema验证、错误处理
|
||
5. **测试编写** - 使用类型安全的测试数据,覆盖正常、异常、边界场景
|
||
|
||
## 必须遵循
|
||
|
||
### 1. 认证与授权
|
||
|
||
```typescript
|
||
// 需要认证的接口必须使用 jwtAuthPlugin
|
||
export const controller = new Elysia().use(jwtAuthPlugin).get('/protected-route', handler, options);
|
||
```
|
||
|
||
### 2. 参数验证与类型使用
|
||
|
||
```typescript
|
||
// example.schema.ts - 定义Schema和导出类型
|
||
import { t, type Static } from 'elysia';
|
||
|
||
export const GetUserByUsernameSchema = t.Object({
|
||
username: t.String({ minLength: 2, maxLength: 50 }),
|
||
});
|
||
|
||
// 导出TypeScript类型
|
||
export type GetUserByUsernameParams = Static<typeof GetUserByUsernameSchema>;
|
||
|
||
// example.service.ts - Service中使用类型
|
||
import type { GetUserByUsernameParams } from './example.schema';
|
||
|
||
export class ExampleService {
|
||
async getUserByUsername(params: GetUserByUsernameParams): Promise<UserInfo> {
|
||
const { username } = params; // 类型安全
|
||
// 业务逻辑...
|
||
}
|
||
}
|
||
|
||
// example.controller.ts - Controller中使用Schema验证
|
||
export const controller = new Elysia().use(jwtAuthPlugin).get('/user/:username', handler, {
|
||
params: GetUserByUsernameSchema, // 运行时验证
|
||
});
|
||
```
|
||
|
||
**要求:**
|
||
- ✅ 每个Schema必须导出对应的TypeScript类型
|
||
- ✅ Service方法必须使用类型注解
|
||
- ❌ 禁止行内定义任何参数Schema
|
||
|
||
### 3. 统一响应格式
|
||
|
||
```typescript
|
||
// 成功响应
|
||
return {
|
||
code: ERROR_CODES.SUCCESS,
|
||
message: '操作成功',
|
||
data: result,
|
||
};
|
||
|
||
// 错误响应
|
||
return {
|
||
code: ERROR_CODES.BUSINESS_ERROR,
|
||
message: '具体错误信息',
|
||
data: null,
|
||
};
|
||
```
|
||
|
||
- 响应内容的类型需要在.response.ts中定义
|
||
|
||
### 4. 错误处理
|
||
|
||
```typescript
|
||
try {
|
||
const result = await service.method();
|
||
return successResponse(result);
|
||
} catch (error) {
|
||
Logger.error(new Error(`操作失败: ${error}`));
|
||
|
||
const errorMessage = error instanceof Error ? error.message : '未知错误';
|
||
if (errorMessage.includes('特定错误')) {
|
||
set.status = 400;
|
||
return errorResponse(ERROR_CODES.BUSINESS_ERROR, '业务错误消息');
|
||
}
|
||
|
||
set.status = 500;
|
||
return errorResponse(ERROR_CODES.INTERNAL_ERROR, '服务器内部错误');
|
||
}
|
||
```
|
||
|
||
### 5. 文档配置
|
||
|
||
```typescript
|
||
{
|
||
detail: {
|
||
summary: '接口简要描述',
|
||
description: '接口详细描述',
|
||
tags: [tags.moduleName],
|
||
security: [{ bearerAuth: [] }], // 需要认证时添加
|
||
},
|
||
response: PredefinedResponses,
|
||
}
|
||
```
|
||
|
||
### 6. 日志记录
|
||
|
||
```typescript
|
||
// 接口调用日志
|
||
Logger.info(`接口被调用,参数: ${param}, 用户: ${JSON.stringify(user)}`);
|
||
|
||
// 成功日志
|
||
Logger.info(`操作成功,结果: ${result.id}`);
|
||
|
||
// 错误日志
|
||
Logger.error(new Error(`操作失败,错误: ${error}`));
|
||
```
|
||
|
||
### 7. 必要的注释
|
||
|
||
1. 接口名称注释
|
||
|
||
```typescript
|
||
export const controller = new Elysia()
|
||
.use(jwtAuthPlugin)
|
||
/**
|
||
* 根据用户名查询用户信息
|
||
* @route GET /api/sample/user/:username
|
||
* @description 通过用户名查询用户的详细信息,需要JWT认证
|
||
* @param username 用户名,路径参数,长度2-50字符
|
||
* @returns 用户信息对象或错误响应
|
||
* @modification hotok 2025-06-29 初始实现
|
||
*/
|
||
.get('/protected-route', handler, options);
|
||
```
|
||
|
||
## 禁止事项
|
||
|
||
- ❌ 直接在 Controller 中写业务逻辑
|
||
- ❌ 不进行参数验证
|
||
- ❌ 返回非标准格式的响应
|
||
- ❌ 暴露敏感信息(如密码哈希)
|
||
- ❌ 缺少错误处理和日志记录
|
||
- ❌ 不编写测试用例
|
||
|
||
## 命名规范
|
||
|
||
- 文件名:`module.type.ts`(如:`user.controller.ts`)
|
||
- Schema:`GetUserByIdSchema`、`CreateUserSchema`
|
||
- Response:`GetUserSuccessResponse`、`UserErrorResponse`
|
||
- Service 类:`UserService`、导出实例:`userService`
|
||
- Controller:`userController`
|
||
|
||
## 测试要求
|
||
|
||
每个接口必须包含:
|
||
|
||
- ✅ 正常流程测试
|
||
- ✅ 参数验证边界测试(最短、最长、无效格式)
|
||
- ✅ 业务逻辑异常测试(不存在、权限不足等)
|
||
- ✅ 认证相关测试(无Token、无效Token、过期Token)
|
||
- ✅ 响应格式验证(状态码、code、message、data结构)
|