project-context.md 15 KB


project_name: '188-179-template-6' user_name: 'Root' date: '2026-01-08T00:00:00.000Z' sections_completed:

  • technology_stack
  • language_rules
  • framework_rules
  • test_rules
  • code_quality_rules
  • anti_patterns status: complete rule_count: 50 optimized_for_llm: true ---

Project Context for AI Agents

This file contains critical rules and patterns that AI agents must follow when implementing code in this project. Focus on unobvious details that agents might otherwise miss.


Technology Stack & Versions

Core Technologies

类别 技术 版本 用途
包管理 pnpm 10.18.3 Monorepo工作空间管理
TypeScript typescript 5.9.3 类型安全,严格模式
前端框架 React 19.1.0 Web应用UI
前端框架 Taro 3.x 小程序开发
构建工具 Vite 7.x 快速构建和热重载
后端框架 Hono 4.8.5 API服务器
数据库ORM TypeORM 0.3.25 数据库操作
数据库 PostgreSQL 17 主数据库
缓存 Redis 7 缓存和会话
存储 MinIO 8.0.5 对象存储

Testing Stack

测试类型 工具 版本 用途
Web/后端测试 Vitest 3.2.4 主要测试运行器
Mini UI测试 Jest 最新 Mini UI包测试
E2E测试 Playwright 1.55.0 端到端测试
组件测试 Testing Library 16.3.0 React组件测试
DOM环境 Happy DOM 18.0.1 轻量级DOM环境

UI Libraries

版本 用途
Radix UI Latest 无障碍组件库
Tailwind CSS 4.1.11 样式框架
Heroicons 2.2.0 图标库
Ant Design Icons 6.0.0 补充图标

Development Environment

  • Node.js: 20.19.2
  • 默认端口: 8080
  • 开发服务器: 自动启动在8080端口
  • 数据库连接: psql -h 127.0.0.1 -U postgres

Critical Implementation Rules

语言特定规则

TypeScript 配置

  • 严格模式: 所有项目启用 strict: true,禁止 any 类型
  • 目标配置: ES2022,ESNext 模块,bundler 解析
  • 类型显式: 函数参数、返回值必须有明确类型注解

命名约定

  • 文件名: kebab-case (如: user.service.ts)
  • 类名: PascalCase (如: UserService)
  • 函数/变量: camelCase (如: getUserById)
  • 常量: UPPER_SNAKE_CASE (如: API_BASE_URL)
  • 接口: PascalCase,无 I 前缀 (如: User)

包间依赖

  • Monorepo 协议: 使用 workspace:* 引用内部包

    "@d8d/shared-types": "workspace:*"
    

RPC 类型安全规范(关键)

  • 响应类型提取: 使用 InferResponseType 从客户端提取

    import type { InferResponseType } from 'hono/client'
    
    // 基础响应类型
    type UserResponse = InferResponseType<typeof userClient.$get, 200>;
    
    // 获取嵌套数据
    type UserData = InferResponseType<typeof userClient.$get, 200>['data'][0];
    
    // ⚠️ 路径参数注意::id 必须用中括号
    type DetailResponse = InferResponseType<typeof userClient[':id']['$get'], 200>;
    
  • 请求类型提取: 使用 InferRequestType 提取

    import type { InferRequestType } from 'hono/client'
    
    // POST 请求体类型
    type CreateUserRequest = InferRequestType<typeof userClient.$post>['json'];
    
    // PUT 请求体类型
    type UpdateUserRequest = InferRequestType<typeof userClient[':id']['$put']>['json'];
    
  • 常见错误:

    // ❌ 错误::id 路径忘记中括号
    InferResponseType<typeof client[':id'].$get, 200>
    
    // ✅ 正确::id 必须用中括号
    InferResponseType<typeof client[':id']['$get'], 200>
    
  • 类型命名规范:

    • 响应类型: [ResourceName]Response
    • 请求类型: [ResourceName]Request

测试与调试

  • 测试运行: pnpm test --testNamePattern "测试名称"
  • Console 输出: Vitest 中只有 console.debug 会显示
  • E2E 调试: 失败时查看 test-results/**/error-context.md
  • 类型导入: 使用 import 配合 vi.mocked,不用 require

Git 操作

  • 锁文件冲突: rm -f .git/index.lock && git add <文件> && git commit -m "消息"

框架特定规则

React 19 (Web UI)

  • 数据获取: 使用 @tanstack/react-query 管理服务器状态
  • 表单管理: 使用 react-hook-form + @hookform/resolvers
  • 组件模式:
    • 编辑/新建使用条件渲染两个独立 Form 组件
    • 不在单个 Form 组件上动态切换 props
  • 测试选择器: 关键元素添加 data-testid,优先 getByTestId()
  • 表单调试:

    form.handleSubmit(handleSubmit, (errors) => console.debug('表单验证错误:', errors))
    

Taro 3.x (小程序)

  • 布局规范:

    // ❌ View 默认横向布局
    <View><Text>行1</Text><Text>行2</Text></View>
    
    // ✅ 添加 flex flex-col
    <View className="flex flex-col">
    <Text>行1</Text>
    <Text>行2</Text>
    </View>
    
  • 图标使用:

    // ✅ 正确:Heroicons 图标类 + 尺寸
    <View className="i-heroicons-chevron-left-20-solid w-5 h-5" />
    
    // ❌ 错误:使用 emoji
    <Text>🔔</Text>
    
  • Navbar 配置:

    • TabBar 页面: leftIcon="", leftText=""
    • 二级页面: leftIcon="i-heroicons-chevron-left-20-solid"
  • 测试框架: 使用 Jest 而非 Vitest

Hono 4.x (API 服务器)

  • 路由定义:

    import { OpenAPIHono } from '@hono/zod-openapi'
    
    const app = new OpenAPIHono()
    
  • 响应验证:

    import { parseWithAwait, createZodErrorResponse } from '@d8d/shared-utils'
    
    app.get('/custom', async (c) => {
    try {
      const result = await service.getData()
      // ✅ 必须验证响应
      const validated = await parseWithAwait(Schema, result)
      return c.json(validated, 200)
    } catch (error) {
      if (error instanceof z.ZodError) {
        return c.json(createZodErrorResponse(error), 400)
      }
    }
    })
    

TypeORM 0.3.25 (数据库)

  • Entity 定义:

    @Entity('table_name')
    export class Example {
    @PrimaryGeneratedColumn({
      name: 'id',
      type: 'int',
      unsigned: true,
      comment: '主键ID'
    })
    id!: number
    
    @Column({
      name: 'field_name',
      type: 'varchar',
      length: 100,
      nullable: false,
      comment: '字段描述'
    })
    @Index('idx_field_name', { unique: true })
    fieldName!: string
    }
    
  • Service 层:

    export class ExampleService extends GenericCrudService<Example> {
    override async create(data: Partial<Example>): Promise<Example> {
      // 业务逻辑检查
      return super.create(data)
    }
    }
    

Zod 4.x (验证)

  • Schema 定义:

    import { z } from 'zod'
    
    export const ExampleSchema = z.object({
    id: z.number().int().positive().openapi({
      description: 'ID',
      example: 1
    }),
    // ✅ Zod 4.0 需要泛型参数
    createdAt: z.coerce.date<Date>().openapi({
      description: '创建时间'
    }),
    amount: z.coerce.number<number>().openapi({
      description: '金额'
    })
    })
    
  • 不导出推断类型: RPC 自动推断,无需手动导出


测试规则

测试框架选择

  • Web/后端测试: Vitest 3.2.4
  • Mini UI 测试: Jest(注意:与 Web 不同)
  • E2E 测试: Playwright 1.55.0
  • 组件测试: Testing Library 16.3.0
  • DOM 环境: Happy DOM 18.0.1

测试文件命名

  • Vitest 测试: *.test.ts
  • Playwright E2E: *.spec.ts
  • 测试位置: tests/unit, tests/integration, tests/e2e

覆盖率目标

  • 单元测试: ≥80%
  • 集成测试: ≥60%
  • 关键流程 E2E: 100%

测试命令

# 运行特定测试
pnpm test --testNamePattern "测试名称"

# Mini UI 测试(使用 Jest)
cd mini && pnpm test --testNamePattern "名称"

# E2E 测试
pnpm test:e2e:chromium

# 类型检查(可用 grep 过滤)
pnpm typecheck 2>&1 | grep "pattern"

调试技巧

  • Vitest: 只有 console.debug 会显示,其他 console 被屏蔽
  • E2E 失败: 先查看 test-results/**/error-context.md
  • 表单调试:

    form.handleSubmit(handleSubmit, (errors) => console.debug('表单验证错误:', errors))
    

测试数据管理

  • 工厂模式: 使用 createTestXxx(overrides) 函数
  • 数据库策略:
    • 单元测试: 内存数据库或 mock
    • 集成测试: 专用测试数据库,事务回滚
    • E2E 测试: 接近生产环境

Mini UI 特殊规则

  • 测试框架: 必须使用 Jest,不能用 Vitest
  • 运行位置: 进入 mini 目录后运行测试
  • API 测试: yongren-api.test.ts, yongren-routes.test.ts

代码质量与风格规则

文档要求

  • JSDoc: 公共 API 必须包含完整 JSDoc 注释

    /**
    * 函数描述(简洁说明)
    *
    * @param paramName - 参数描述
    * @param paramTwo - 参数描述
    * @throws {ErrorType} 错误条件
    * @example
    * ```ts
    * await functionName(page, 'arg', 'value');
    * ```
    */
    
  • README: 每个包必须有独立的 README 说明用途和使用方法

  • 关键逻辑: 复杂业务逻辑必须添加注释说明

代码风格

  • 缩进: 使用 2 个空格(不使用 tab)
  • 格式化: 使用 Prettier 统一代码格式
  • Linting: ESLint 配置 TypeScript 和 React 规则
  • 提交前检查: 使用 husky 进行 pre-commit 钩子检查

代码组织

  • 包结构:

    packages/example-module/
    ├── src/
    │   ├── entities/        # 数据实体
    │   ├── services/        # 业务逻辑
    │   ├── schemas/         # 验证 Schema
    │   ├── routes/          # API 路由
    │   ├── middleware/      # 中间件
    │   ├── utils/           # 工具函数
    │   └── index.ts         # 包入口
    ├── tests/
    └── README.md
    
  • 导出规范: 在 index.ts 统一导出

    export * from './entities';
    export * from './services';
    export { exampleRoutes } from './routes';
    export { exampleSchema } from './schemas';
    

安全最佳实践

  • 输入验证: 使用 Zod Schema 验证所有输入
  • 敏感数据: 从响应中排除密码等敏感字段
  • SQL 注入: 使用 TypeORM 参数化查询,不拼接 SQL
  • 日志: 不在日志中记录敏感信息

性能优化

  • 数据库查询: 只查询需要的字段,使用索引
  • N+1 避免: 使用 relations 而非循环查询
  • 缓存: 使用 Redis 缓存热点数据

关键禁止规则(Anti-Patterns)

TypeScript 类型禁令

// ❌ 禁止:使用 any 类型
function process(data: any) { }

// ❌ 禁止:直接导入 schema 类型(可能导致 Date/string 不匹配)
import { UserSchema } from './schema';
type User = z.infer<typeof UserSchema>;

// ❌ 禁止:Zod 4.0 缺少泛型参数
createdAt: z.coerce.date()
amount: z.coerce.number()

// ✅ 正确:使用 RPC 推断类型
type UserResponse = InferResponseType<typeof userClient.$get, 200>;
type UserData = InferResponseType<typeof userClient.$get, 200>['data'][0];

React/UI 禁令

// ❌ 禁止:在单个 Form 组件上动态切换 props
<Form mode={isEdit ? 'edit' : 'create'} />

// ✅ 正确:使用条件渲染两个独立 Form
{isEdit ? <EditForm /> : <CreateForm />}

// ❌ 禁止:使用 getByText 查找可能重复的文本
screen.getByText('保存')

// ✅ 正确:添加 data-testid 并使用
<button data-testid="save-button">保存</button>
screen.getByTestId('save-button')

// ❌ 禁止:RPC 路径参数忘记中括号
InferResponseType<typeof client[':id'].$get, 200>

// ✅ 正确::id 必须用中括号
InferResponseType<typeof client[':id']['$get'], 200>

Mini UI 禁令

// ❌ 禁止:忘记 flex flex-col
<View>
  <Text>行1</Text>
  <Text>行2</Text>
</View>

// ✅ 正确:添加 flex flex-col
<View className="flex flex-col">
  <Text>行1</Text>
  <Text>行2</Text>
</View>

// ❌ 禁止:使用 emoji 图标
<Text>🔔</Text>
<Text>←</Text>

// ✅ 正确:使用 Heroicons 图标类
<View className="i-heroicons-bell-20-solid w-5 h-5" />
<View className="i-heroicons-chevron-left-20-solid w-5 h-5" />

// ❌ 禁止:在 Mini UI 包内使用别名导入
import { utils } from '@/utils'

// ✅ 正确:使用相对路径
import { utils } from '../../utils'

后端模块禁令

// ❌ 禁止:Entity 列定义省略属性
@Column({ name: 'email' })
email!: string;

// ✅ 正确:完整定义
@Column({
  name: 'email',
  type: 'varchar',
  length: 100,
  nullable: false,
  comment: '邮箱'
})
email!: string;

// ❌ 禁止:覆盖方法不使用 override
async create(data: Partial<T>): Promise<T> {
  return super.create(data);
}

// ✅ 正确:使用 override 关键字
override async create(data: Partial<T>): Promise<T> {
  return super.create(data);
}

// ❌ 禁止:自定义路由不验证响应
app.get('/custom', async (c) => {
  const result = await service.getData();
  return c.json(result, 200);
})

// ✅ 正确:使用 parseWithAwait 验证
app.get('/custom', async (c) => {
  const result = await service.getData();
  const validated = await parseWithAwait(Schema, result);
  return c.json(validated, 200);
})

// ❌ 禁止:物理删除
await repository.delete(id);

// ✅ 正确:使用 status 字段软删除
await repository.update(id, { status: 0 });

测试禁令

// ❌ 禁止:在 Vitest 中使用 console.log(被屏蔽)
console.log('debug info');

// ✅ 正确:使用 console.debug
console.debug('debug info');

// ❌ 禁止:Mini UI 使用 Vitest
// mini-ui-packages/xxx/package.json
"test": "vitest"

// ✅ 正确:Mini UI 使用 Jest
"test": "jest"

// ❌ 禁止:测试中使用 require
const utils = require('./utils');

// ✅ 正确:使用 import
import { utils } from './utils';
// 配合 vi.mocked 使用
const mockedUtils = vi.mocked(utils);

项目结构概览

188-179-template-6/
├── packages/           # 核心共享包和业务模块 (61个)
├── allin-packages/     # AllIn业务模块 (15个)
├── mini-ui-packages/   # 小程序UI组件库 (18个)
├── web/                # 管理后台应用
├── mini/               # 员工小程序 (Taro)
├── mini-talent/        # 人才小程序 (Taro)
├── docs/               # 项目文档
└── _bmad-output/       # BMAD工作流输出

开发快速命令

# 启动所有应用
pnpm dev

# 仅启动管理后台
pnpm run dev:web

# 构建所有包
pnpm build

# 运行测试
pnpm test

# 类型检查
pnpm typecheck

使用指南

给 AI Agent

  • 实施前必读: 在编写任何代码之前,请完整阅读此文件
  • 严格遵循: 完全按照文档中记录的所有规则实施
  • 存疑时: 当不确定时,选择更严格的选项
  • 更新维护: 当出现新模式时,更新此文件

给人类开发者

  • 保持精简: 保持此文件专注于 AI Agent 的需求
  • 技术栈变更: 当技术栈变化时更新
  • 季度评审: 定期评审以删除过时规则
  • 移除明显规则: 随时间推移移除变得显而易见的规则

最后更新

日期: 2026-01-08 版本: 1.0 状态: 已完成,已针对 LLM 优化


此文档由 generate-project-context 工作流生成。更新项目时请保持此文档同步。