This commit is contained in:
D8D Developer
2025-06-27 01:56:30 +00:00
parent 0ef1dd1484
commit b9a3c991d0
354 changed files with 5 additions and 5 deletions

15
.roo/mcp.json Normal file
View File

@@ -0,0 +1,15 @@
{
"mcpServers": {
"openapi": {
"command": "npx",
"args": [
"-y",
"mcp-openapi-schema-explorer@latest",
"https://pre-136-107-template-6.r.d8d.fun/doc",
"--output-format",
"json"
],
"env": {}
}
}
}

25
.roo/rules/01-general.md Normal file
View File

@@ -0,0 +1,25 @@
# 基础规范
## 项目结构
```
src/
├── client/ # 前端代码 (React + Vite)
├── server/ # 后端代码 (Hono + TypeORM)
│ ├── api/ # API路由
│ ├── migrations/ # 数据库迁移脚本
│ ├── modules/ # 业务模块
│ └── middleware/ # 中间件
```
## 技术栈
### 前端
- React 18
- TypeScript (严格模式)
- Vite 构建工具
### 后端
- Hono 框架
- TypeORM (mysql)
- Redis (缓存/会话管理)

View File

@@ -0,0 +1,5 @@
# TypeScript规范
1. **严格模式**
- 启用所有严格类型检查选项
- 避免使用`any`类型

8
.roo/rules/03-modules.md Normal file
View File

@@ -0,0 +1,8 @@
# 模块化规范
1. **模块组织**
- 按功能划分模块
- 每个模块包含:
- 实体定义
- 服务层
- 路由控制器

22
.roo/rules/04-api.md Normal file
View File

@@ -0,0 +1,22 @@
# 接口定义规范
1. **DTO定义**
- 必须包含`description`字段说明用途
- 必须包含`example`字段提供示例值
- 示例:
```typescript
export const CreateUserDto = z.object({
username: z.string().min(3).max(20).openapi({
example: 'john_doe',
description: '用户名, 3-20个字符'
}),
password: z.string().min(6).openapi({
example: 'password123',
description: '密码, 最少6位'
})
})
```
2. **API响应**
- 统一的API响应格式
- 完善的Swagger文档

View File

@@ -0,0 +1,5 @@
# 数据库规范
1. **迁移管理**
- 使用迁移脚本管理表结构变更
- 实体类与数据库表严格映射

View File

@@ -0,0 +1,19 @@
# 依赖注入规范
1. **依赖注入原则**
- 服务类必须通过构造函数注入依赖
- 禁止直接实例化全局对象(AppDataSource等)
- 不需要import { Injectable } from '@nestjs/common';, 本项目没用@nestjs
- 示例:
```typescript
// Good - 通过构造函数注入
export class UserService {
constructor(private dataSource: DataSource) {}
}
// Bad - 使用全局实例
export class UserService {
constructor() {
this.repository = AppDataSource.getRepository(User);
}
}

272
.roo/rules/07-openapi.md Normal file
View File

@@ -0,0 +1,272 @@
# 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()自动转换字符串参数
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;
```

82
.roo/rules/08-rpc.md Normal file
View File

@@ -0,0 +1,82 @@
# RPC 调用规范
## 常见不规范问题
1. **InferResponseType有[':id']时问题**:
- ❌ InferResponseType<typeof zichanClient[':id'].$get, 200>
- ✅ $get要加中括号 InferResponseType<typeof zichanClient[':id']['$get'], 200>
## 核心原则
1. **类型安全**:
- 所有RPC调用必须基于OpenAPI定义的类型
- 客户端和服务端类型必须严格匹配
2. **一致性**:
- RPC调用路径必须与OpenAPI路由定义一致
- 错误处理格式必须统一
3. **api版本**:
- 所有RPC调用必须基于OpenAPI定义的版本
- 版本号必须与OpenAPI版本号一致
目前仅支持v1版本
示例:
```typescript
import { authClient } from '@/client/api';
```
## 客户端规范
### 1. 客户端初始化
```typescript
import { hc } from 'hono/client'
import { AuthRoutes } from '@/server/api';
export const authClient = hc<AuthRoutes>('/', {
fetch: axiosFetch,
}).api.v1.auth;
```
### 2. 方法调用
- 必须使用解构方式组织RPC方法
- 方法命名必须与OpenAPI路由定义一致
- 示例:
```typescript
const res = await authClient.templates.blank[':templateType'].$get({
param: {
templateType
}
});
if (res.status !== 200) {
throw new Error(res.message);
}
const templateInfo = await res.json();
```
### 3. 类型提取规范
- **响应类型提取**:
- 使用 `InferResponseType` 从客户端方法提取响应类型
- 必须指定正确的响应状态码(通常为200)
- 示例:
```typescript
type ResponseType = InferResponseType<typeof client.method.$get, 200>['data'];
```
- **请求类型提取**:
- 使用 `InferRequestType` 从客户端方法提取请求类型
- 必须指定正确的请求参数类型('json'|'form'|'param')
- 示例:
```typescript
type RequestType = InferRequestType<typeof client.method.$post>['json'];
```
- **类型命名规范**:
- 响应类型: `[ResourceName]`
- 请求类型: `[ResourceName]Post` 或 `[ResourceName]Put`
- 示例:
```typescript
import type { InferRequestType, InferResponseType } from 'hono/client'
type ZichanInfo = InferResponseType<typeof zichanClient.$get, 200>['data'][0];
type ZichanListResponse = InferResponseType<typeof zichanClient.$get, 200>;
type ZichanDetailResponse = InferResponseType<typeof zichanClient[':id']['$get'], 200>;
type CreateZichanRequest = InferRequestType<typeof zichanClient.$post>['json'];
type UpdateZichanRequest = InferRequestType<typeof zichanClient[':id']['$put']>['json'];
type DeleteZichanResponse = InferResponseType<typeof zichanClient[':id']['$delete'], 200>;
```

71
.roo/rules/09-logging.md Normal file
View File

@@ -0,0 +1,71 @@
# 日志规范
## 1. 基础配置
- 前后端统一使用debug库
- 开发环境:启用所有日志级别
- 生产环境:通过环境变量`DEBUG`控制日志级别
- 安装依赖:已安装`debug@4.4.1``@types/debug`
## 2. 命名空间规范
格式:`<应用>:<模块>:<功能>`
示例:
```
frontend:auth:login # 前端-认证-登录
backend:api:middleware # 后端-API-中间件
backend:db:query # 后端-数据库-查询
k8s:deployment:create # K8S-部署-创建
```
## 3. 日志级别
| 级别 | 使用场景 |
|--------|----------------------------|
| error | 系统错误、异常情况 |
| warn | 警告性事件 |
| info | 重要业务流程信息 |
| debug | 调试信息 |
| trace | 详细跟踪信息(慎用) |
## 4. 实现示例
### 前端示例
```typescript
// src/client/utils/logger.ts
import debug from 'debug';
export const logger = {
error: debug('frontend:error'),
api: debug('frontend:api'),
auth: debug('frontend:auth'),
ui: debug('frontend:ui')
};
```
### 后端示例
```typescript
// src/server/utils/logger.ts
import debug from 'debug';
export const logger = {
error: debug('backend:error'),
api: debug('backend:api'),
db: debug('backend:db'),
middleware: debug('backend:middleware')
};
```
## 5. 最佳实践
1. 错误日志必须包含错误堆栈和上下文
2. 禁止记录密码、token等敏感信息
3. 生产环境避免使用trace级别
4. 复杂对象使用JSON.stringify()
## 6. 环境配置
```bash
# 开发环境
DEBUG=*
# 生产环境
DEBUG=*:error,*:warn
# 特定模块调试
DEBUG=backend:api,backend:db

117
.roo/rules/10-entity.md Normal file
View File

@@ -0,0 +1,117 @@
# 数据库实体规范
## 1. 实体基础结构
```typescript
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { z } from 'zod';
@Entity('table_name') // 使用小写下划线命名表名
export class EntityName {
// 字段定义...
}
```
## 2. 主键定义规范
```typescript
@PrimaryGeneratedColumn({ unsigned: true }) // 必须使用无符号整数
id!: number; // 使用非空断言(!)和明确类型
```
## 3. 列定义规范
```typescript
@Column({
name: '字段名称', // 必须添加并与数据表字段名称一致
type: 'varchar', // 明确指定数据库类型
length: 255, // 字符串必须指定长度
nullable: true, // 明确是否可为空
default: undefined, // 默认值(可选)
comment: '字段说明' // 必须添加中文注释
})
fieldName!: FieldType; // 类型必须明确
```
## 4. 数据类型规范
| 业务类型 | 数据库类型 | TypeScript 类型 |
|----------------|-------------------------|-----------------------|
| 主键ID | int unsigned | number |
| 短文本 | varchar(length) | string |
| 长文本 | text | string |
| 整数 | int | number |
| 小数 | decimal(precision,scale)| number |
| 布尔状态 | tinyint | number (0/1) |
| 日期时间 | timestamp | Date |
## 5. 状态字段规范
```typescript
// 禁用状态 (0启用 1禁用)
@Column({ name: 'is_disabled', type: 'tinyint', default: 1 })
isDisabled!: number;
// 删除状态 (0未删除 1已删除)
@Column({ name: 'is_deleted',type: 'tinyint', default: 0 })
isDeleted!: number;
```
## 6. 时间字段规范
```typescript
// 创建时间 (自动设置)
@Column({
name: 'created_at',
type: 'timestamp',
default: () => 'CURRENT_TIMESTAMP'
})
createdAt!: Date;
// 更新时间 (自动更新)
@Column({
name: 'updated_at',
type: 'timestamp',
default: () => 'CURRENT_TIMESTAMP',
onUpdate: 'CURRENT_TIMESTAMP'
})
updatedAt!: Date;
```
## 7. Zod Schema 规范
```typescript
export const EntitySchema = z.object({
id: z.number().int().positive().openapi({ description: 'ID说明' }),
// 字符串字段
fieldName: z.string()
.max(255)
.nullable()
.openapi({
description: '字段说明',
example: '示例值'
}),
// 数字字段
numberField: z.number()
.default(默认值)
.openapi({...}),
// 日期字段
dateField: z.date().openapi({...})
});
```
## 8. 命名规范
- 实体类名PascalCase (如 RackInfo)
- 表名snake_case (如 rack_info)
- 字段名camelCase (如 rackName)
- 数据库列名snake_case (如 rack_name)
## 9. 最佳实践
1. 所有字段必须添加字段名称(name)及注释(comment)
2. 必须明确指定 nullable 属性
3. 状态字段使用 tinyint 并注明取值含义
4. 必须包含 createdAt/updatedAt 时间字段
5. 每个实体必须配套 Zod Schema 定义
6. Schema 必须包含 OpenAPI 元数据(description/example)

View File

@@ -0,0 +1,51 @@
# 新实体创建流程规范
## 完整开发流程
1. **创建实体**
- 位置: `src/server/modules/[模块名]/[实体名].entity.ts`
- 参考已有实体文件如`user.entity.ts`
- 注意: 必须包含Zod Schema定义
2. **创建Service**
- 位置: `src/server/modules/[模块名]/[实体名].service.ts`
- 通过构造函数注入DataSource
- 使用实体Schema进行输入输出验证
3. **创建API路由**
- 目录结构:
```
src/server/api/[实体名]/
├── get.ts # 列表
├── post.ts # 创建
├── [id]/
│ ├── get.ts # 详情
│ ├── put.ts # 更新
│ └── delete.ts # 删除
└── index.ts # 路由聚合
```
- 必须使用实体Schema作为请求/响应Schema
- 参考`users`模块的实现
4. **注册路由**
- 在`src/server/api.ts`中添加路由注册
5. **创建客户端API**
- 在`src/client/api.ts`中添加客户端定义
6. **前端调用**
- 在页面组件(如`pages_users.tsx`)中:
- 使用`InferResponseType`提取响应类型
- 使用`InferRequestType`提取请求类型
- 示例:
```typescript
type EntityResponse = InferResponseType<typeof entityClient.$get, 200>;
type CreateRequest = InferRequestType<typeof entityClient.$post>['json'];
```
## 注意事项
1. 实体Schema必须在实体文件中定义路由中直接引用不要重复定义
2. 前端表格/表单字段必须与实体定义保持一致
3. 确保所有API调用都有正确的类型推断
4. 参考现有模块实现保持风格一致