--- alwaysApply: true --- # Bun Elysia框架业务开发规则 ## 0. 概览 这是一个基于 **Bun + Elysia** 的现代化后端API项目,采用TypeScript开发,集成了MySQL、Redis、JWT认证、Swagger文档等功能。 - **运行时**:Bun - **框架**:Elysia - **语言**:TypeScript - **数据库**:MySQL + Drizzle ORM - **缓存**:Redis - **认证**:JWT - **测试**:Vitest - **文档**:Swagger - **日志**:Winston - **代码规范**:ESLint + Prettier - 📂 根目录结构 ``` project/ ├── 📋 配置文件(config/) ├── 📁 源代码 (src/) ├── 📁 文档 (docs/) ├── 📁 需求文档 (prd/) ├── 📁 任务管理 (tasks/) ├── 📁 AI对话记录 (aiChat/) └── 📁 静态资源 (public/) ``` - 🔧 配置文件 | 文件 | 说明 | |------|------| | `package.json` | 项目依赖和脚本配置 | | `tsconfig.json` | TypeScript编译配置 | | `tsconfig.test.json` | 测试环境TypeScript配置 | | `vitest.config.ts` | Vitest测试框架配置 | | `eslint.config.js` | ESLint代码规范配置 | | `bunfig.toml` | Bun运行时配置 | | `bun.lock` | Bun依赖锁定文件 | | `README.md` | 项目说明文档 | - 应用入口 ``` src/ ├── app.ts # Elysia应用主入口 └── server.ts # 服务器启动文件 ``` - 配置管理 (config/) ``` src/config/ ├── index.ts # 配置总入口 ├── db.config.ts # 数据库配置 ├── redis.config.ts # Redis配置 ├── jwt.config.ts # JWT配置 └── logger.config.ts # 日志配置 ``` - 数据实体 (eneities/) ``` src/eneities/ ├── index.ts # 实体总入口 └── users.ts # 用户实体定义 ``` - 业务模块 (modules/) ``` src/modules/ ├── index.ts # 模块总入口 ├── tags.ts # Swagger标签定义 ├── example/ # 示例模块 │ ├── example.schema.ts # Schema定义 │ ├── example.response.ts # 响应格式 │ ├── example.service.ts # 业务逻辑 │ ├── example.controller.ts # 路由控制器 │ └── example.test.ts # 测试用例 ├── health/ # 健康检查模块 │ ├── health.controller.ts │ └── health.service.ts ├── user/ # 用户模块 │ └── user.controller.ts └── test/ # 测试模块 └── test.controller.ts ``` - 插件系统 (plugins/) ``` src/plugins/ ├── index.ts # 插件总入口 ├── drizzle/ # 数据库ORM插件 │ ├── drizzle.config.ts │ ├── drizzle.plugins.ts │ ├── drizzle.service.ts │ └── README.md ├── errorHandle/ # 错误处理插件 │ └── errorHandler.plugins.ts ├── jwt/ # JWT认证插件 │ ├── jwt.plugins.ts │ └── jwt.service.ts ├── logger/ # 日志插件 │ ├── logger.plugins.ts │ └── logger.service.ts ├── redis/ # Redis插件 │ ├── redis.plugins.ts │ └── redis.service.ts └── swagger/ # API文档插件 └── swagger.plugins.ts ``` - 类型定义 (type/) ``` src/type/ ├── config.type.ts # 配置相关类型 ├── drizzle.type.ts # 数据库相关类型 ├── error.type.ts # 错误相关类型 ├── jwt.type.ts # JWT相关类型 ├── logger.type.ts # 日志相关类型 └── redis.type.ts # Redis相关类型 ``` - 工具函数 (utils/) ``` src/utils/ ├── deviceInfo.ts # 设备信息工具 ├── formatFileSize.ts # 文件大小格式化 ├── formatRoute.ts # 路由格式化 ├── jwt.helper.ts # JWT工具函数 ├── mysql.ts # MySQL工具 ├── randomChalk.ts # 随机颜色工具 ├── redis.ts # Redis工具 ├── text.ts # 文本处理工具 └── response.helper.ts # 响应格式工具 (新增) ``` - 验证器 (validators/) ``` src/validators/ └── global.response.ts # 全局响应格式验证 ``` - 测试文件 (tests/) ``` src/tests/ ├── app.test.ts # 应用测试 ├── health.test.ts # 健康检查测试 ├── mysql.test.ts # MySQL测试 ├── redis.test.ts # Redis测试 ├── swagger.test.ts # Swagger测试 └── demo/ └── testLogger.ts # 日志测试演示 ``` - 常量定义 (constants/) ``` src/constants/ └── error-codes.ts # 统一错误码定义 (新增) ``` ## 1. 文件组织规范 ### 1.1 必须的文件结构 每个业务模块必须包含以下5个文件,**按照固定顺序**: ``` src/modules/[module]/ ├── [module].schema.ts # 1️⃣ 数据结构定义(优先级最高) ├── [module].response.ts # 2️⃣ 响应格式定义 ├── [module].service.ts # 3️⃣ 业务逻辑实现 ├── [module].controller.ts # 4️⃣ 路由控制器 └── [module].test.ts # 5️⃣ 测试用例 ``` ### 1.2 文件命名约定 - 模块名使用 **单数形式**:`user`、`product`、`order`(不是 users、products) - 文件名格式:`[模块名].[类型].ts` - 导出名格式:`[模块名][类型名]` ## 2. Schema & 类型系统(🔥 重点) ### 2.1 Schema定义规范 ```typescript // ✅ 正确示例 - user.schema.ts import { t, type Static } from 'elysia'; // 1. 定义Schema(运行时验证) export const CreateUserSchema = t.Object({ username: t.String({ minLength: 2, maxLength: 50, description: '用户名,2-50字符', examples: ['admin', 'testuser'] }), email: t.String({ format: 'email', description: '用户邮箱', examples: ['user@example.com'] }), password: t.String({ minLength: 6, description: '密码,至少6位', examples: ['123456'] }), }); // 2. 导出TypeScript类型(编译时类型检查) export type CreateUserRequest = Static; // 3. 数据模型Schema export const UserSchema = t.Object({ id: t.Number({ description: '用户ID' }), username: t.String({ description: '用户名' }), email: t.String({ description: '邮箱' }), createdAt: t.String({ description: '创建时间' }), updatedAt: t.String({ description: '更新时间' }), }); export type User = Static; ``` ### 2.2 类型导出规范 **必须遵循的命名模式:** - Request类型:`[动作][模块]Request` → `CreateUserRequest` - Response类型:`[动作][模块]Response` → `GetUserResponse` - 数据模型:`[模块]` → `User`、`Product` - Schema名:`[动作][模块]Schema` → `CreateUserSchema` ## 3. Response定义规范 ### 3.1 统一响应格式 ```typescript // ✅ 正确示例 - user.response.ts import { t, type Static } from 'elysia'; import { globalResponseWrapperSchema } from '@/validators/global.response'; import { UserSchema } from './user.schema'; // 成功响应 export const GetUserSuccessResponseSchema = globalResponseWrapperSchema(UserSchema); export type GetUserSuccessResponse = Static; // 错误响应 export const UserNotFoundResponseSchema = t.Object({ code: t.Literal('USER_NOT_FOUND'), message: t.String({ examples: ['用户不存在'] }), data: t.Null(), }); export type UserNotFoundResponse = Static; // 组合响应(供controller使用) export const GetUserResponses = { 200: GetUserSuccessResponseSchema, 404: UserNotFoundResponseSchema, 401: t.Object({ code: t.Literal('UNAUTHORIZED'), message: t.String(), data: t.Null(), }), }; ``` ## 4. Service层规范 ### 4.1 Service类定义 ```typescript // ✅ 正确示例 - user.service.ts import type { CreateUserRequest, User } from './user.schema'; import type { GetUserSuccessResponse, UserNotFoundResponse } from './user.response'; import { Logger } from '@/plugins/logger/logger.service'; import { ERROR_CODES } from '@/constants/error-codes'; export class UserService { /** * 创建用户 * @param request 创建用户请求参数 * @returns Promise */ async createUser(request: CreateUserRequest): Promise { try { Logger.info(`创建用户请求:${JSON.stringify(request)}`); // 业务逻辑实现 const user: User = { id: 1, username: request.username, email: request.email, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; // 进行数据库操作逻辑... Logger.info(`用户创建成功:${user.id}`); return { code: ERROR_CODES.SUCCESS, message: '用户创建成功', data: user, }; } catch (error) { Logger.error(new Error(`创建用户失败:${error}`)); throw error; } } /** * 根据ID查询用户 * @param id 用户ID * @returns Promise */ async getUserById(id: number): Promise { // 实现逻辑... } } // 导出单例实例 export const userService = new UserService(); ``` ### 4.2 Service层要求 - ✅ 所有方法必须有完整的类型注解 - ✅ 所有方法必须有JSDoc注释 - ✅ 必须有详细的日志记录 - ✅ 必须有错误处理 - ✅ 导出单例实例供controller使用 ## 5. Controller层规范 ### 5.1 Controller定义 ```typescript // ✅ 正确示例 - user.controller.ts import { Elysia } from 'elysia'; import { jwtAuthPlugin } from '@/plugins/jwt/jwt.plugins'; import { CreateUserSchema } from './user.schema'; import { GetUserResponses } from './user.response'; import { userService } from './user.service'; import { tags } from '@/modules/tags'; export const userController = new Elysia({ prefix: '/user' }) /** * 创建用户 * @route POST /api/user */ .post( '/', ({ body }) => userService.createUser(body);, { body: CreateUserSchema, detail: { summary: '创建用户', description: '创建新用户账户', tags: [tags.user], }, response: GetUserResponses, } ) /** * 获取用户信息(需要认证) * @route GET /api/user/:id */ .use(jwtAuthPlugin) .get( '/:id', async ({ params }) => userService.getUserById(Number(params.id));, { params: t.Object({ id: t.Numeric({ description: '用户ID' }) }), detail: { summary: '获取用户信息', description: '根据用户ID获取用户详细信息', tags: [tags.user], security: [{ bearerAuth: [] }], }, response: GetUserResponses, } ); ``` ## 6. 错误处理规范 ### 6.1 统一错误码 ```typescript // src/constants/error-codes.ts export const ERROR_CODES = { SUCCESS: 'SUCCESS', VALIDATION_ERROR: 'VALIDATION_ERROR', UNAUTHORIZED: 'UNAUTHORIZED', FORBIDDEN: 'FORBIDDEN', NOT_FOUND: 'NOT_FOUND', BUSINESS_ERROR: 'BUSINESS_ERROR', INTERNAL_ERROR: 'INTERNAL_ERROR', } as const; ``` ### 6.2 错误处理模式 ```typescript // Service层 try { // 业务逻辑 const result = await someOperation(); return successResponse(result); } catch (error) { Logger.error(new Error(`操作失败:${error}`)); if (error instanceof ValidationError) { throw new BusinessError('参数验证失败', ERROR_CODES.VALIDATION_ERROR); } throw new InternalError('内部服务错误', ERROR_CODES.INTERNAL_ERROR); } // Controller层 try { const result = await service.method(); return result; } catch (error) { if (error instanceof BusinessError) { set.status = 400; return errorResponse(error.code, error.message); } set.status = 500; return errorResponse(ERROR_CODES.INTERNAL_ERROR, '服务器内部错误'); } ``` ## 7. 测试规范 ### 7.1 测试文件结构 ```typescript // ✅ 正确示例 - user.test.ts import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { app } from '@/app'; import type { CreateUserRequest } from './user.schema'; describe('User API', () => { let authToken: string; beforeAll(async () => { // 设置测试环境 authToken = 'test-jwt-token'; }); describe('POST /api/user', () => { it('应该成功创建用户', async () => { const payload: CreateUserRequest = { username: 'testuser', email: 'test@example.com', password: '123456', }; const response = await app .handle(new Request('http://localhost/api/user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), })); expect(response.status).toBe(200); const result = await response.json(); expect(result.code).toBe('SUCCESS'); expect(result.data.username).toBe(payload.username); }); it('应该验证必填字段', async () => { const payload = { username: 'test' }; // 缺少email和password const response = await app .handle(new Request('http://localhost/api/user', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), })); expect(response.status).toBe(400); }); }); }); ``` ## 8. AI助手协作规范 ### 8.1 注释规范(关键❗️) #### 1. 文件头部注释 每个源文件开头应包含如下信息: ```javascript /** * @file 文件简要说明 * @author 创建者姓名(如:张三 ) * @date 创建时间(如:2024-06-01) * @lastEditor 最后修改人 * @lastEditTime最后修改时间 * @description 文件详细描述(可选) */ ``` #### 2. 函数/方法/请求注释(JSDoc) - 每个公开函数、类、接口都应有 JSDoc 注释 - 增加修改记录,包含修改人、修改时间、修改描述 **推荐标签:** - `@param` 参数说明 - `@returns` 返回值说明 - `@throws` 可能抛出的异常 - `@deprecated` 弃用说明 - `@example` 使用示例 - `@modification` 修改记录(格式:修改人 修改时间 修改描述) **示例:** ```typescript /** * 计算两个数的和 * @param a 第一个加数 * @param b 第二个加数 * @returns 两数之和 * @example * add(1, 2) // 3 * @modification 李四 2024-06-05 优化了参数校验 */ function add(a: number, b: number): number { return a + b; } ``` ```typescript /** * 方法功能说明 * @route HTTP方法 路径 * @description 详细描述 * @param 参数名 参数说明 * @returns 返回值类型和说明 * @throws 可能抛出的异常 * @example 使用示例 * @modification 作者 日期 修改说明 */ ``` #### 3. 注释类型与风格 - 单行注释:`//`,用于简短说明 - 多行注释:`/* ... */`,用于较长描述 - 文档注释(JSDoc):`/** ... */`,用于结构化说明 - 注释应简洁明了,避免废话和重复代码内容 - 注释内容使用中文或英文均可,但需统一 - 代码变更时同步更新相关注释,避免注释与代码不符 - 不要注释掉无用代码,直接删除,必要时可通过版本管理找回 #### 4. 特殊标记 - `TODO:` 需要补充或优化的内容 - `FIXME:` 需要修复的问题 - `HACK:` 临时解决方案,需后续优化 **示例:** ```javascript // TODO: 优化此处的性能 // FIXME: 这里有边界条件未处理 // HACK: 临时绕过接口校验 ``` #### 5. 变量注释 - 每一个变量遵照JSDoc添加注释,携带描述、用途 参照 ```ts /** * MySQL数据库连接配置 * @property {string} host - 数据库主机地址 * @property {number} port - 数据库端口号 * @property {string} user - 数据库用户名 * @property {string} password - 数据库密码 * @property {string} database - 数据库名称 */ export const dbConfig = { /** 数据库主机地址 */ host: process.env.DB_HOST || 'localhost', /** 数据库端口号 */ port: Number(process.env.DB_PORT) || 3306, /** 数据库用户名 */ user: process.env.DB_USER || 'root', /** 数据库密码 */ password: process.env.DB_PASSWORD || '', /** 数据库名称 */ database: process.env.DB_NAME || 'test', }; ``` #### 6. 规范补充建议 - 注释应随代码同步更新,避免"注释失效"或误导他人。 - 代码评审时,建议同时检查注释的准确性和完整性。 - 复杂算法、业务逻辑、边界处理、特殊依赖等务必详细注释。 - 简单、易懂的代码无需过度注释,避免注释冗余。 - 团队应约定注释统一使用中文或英文,避免混杂,提升协作效率。 - 推荐使用 ESLint、TSLint 等工具结合注释相关插件(如 eslint-plugin-jsdoc)进行注释规范自动校验。 - 可使用 IDE 插件(如 VSCode 的 JSDoc Generator)自动生成注释模板,提升效率。 - 建议在项目根目录下提供注释模板(如 `.comment-templates`),便于新成员快速上手。 - 注释中严禁出现密码、密钥、用户隐私等敏感信息。 - 重要模块、核心业务建议将注释内容同步到项目文档,便于知识传承和查阅。 ### 8.2 代码组织原则 1. **单一职责**:每个文件只负责一个清晰的功能 2. **依赖注入**:通过构造函数或导入明确依赖关系 3. **类型优先**:先定义Schema和类型,再实现逻辑 4. **错误优先**:优先考虑错误处理和边界情况 5. **测试驱动**:每个功能都有对应的测试用例 ### 8.3 命名约定总结 | 类型 | 格式 | 示例 | |------|------|------| | 文件名 | `[module].[type].ts` | `user.controller.ts` | | Schema | `[Action][Module]Schema` | `CreateUserSchema` | | Type | `[Action][Module][Type]` | `CreateUserRequest` | | Service类 | `[Module]Service` | `UserService` | | Service实例 | `[module]Service` | `userService` | | Controller | `[module]Controller` | `userController` | ## 9. 快速检查清单 开发新功能时,按此顺序检查: - [ ] 1. Schema定义完整(包含验证规则和示例) - [ ] 2. 类型导出正确(Request/Response类型) - [ ] 3. Response格式统一(成功/错误响应) - [ ] 4. Service类型注解完整 - [ ] 5. Controller错误处理完整 - [ ] 6. 测试用例覆盖主要场景 - [ ] 7. JSDoc注释完整 - [ ] 8. 日志记录到位 ## 10. 最佳实践 ### 10.1 性能优化 - 使用连接池管理数据库连接 - 实现合理的缓存策略 - 避免N+1查询问题 ### 10.2 安全考虑 - 输入验证和清理 - 适当的认证和授权 - 敏感信息不记录日志 ### 10.3 监控和日志 - 关键操作必须有日志 - 错误信息要有足够上下文 - 性能敏感操作要有监控 这套规则确保了代码的一致性、可维护性和AI友好性,让我能够更高效地理解和协助你的开发工作。 ## 11. 模块引入 - 全部使用路径别名,如`@/app` `@/config/db.config` - 注意更新 tsconfig.json bunfig.toml 等配置中关于路径别名的配置 --- **请所有开发者严格遵守以上规范,保障 Elysia 接口的一致性、后端服务的健壮性、安全性与可维护性。**