Files
Alfred/docs/development/backend.md
lanyuanxiaoyao 2ea4bd4410 test: 测试体系全面优化,修复 Windows SQLite EBUSY 和前端产品缺陷
测试基础设施
- 统一 SQLite 测试 DB/临时目录 helper(tests/helpers.ts),支持 Windows EBUSY 重试清理
- 测试库使用 PRAGMA journal_mode=DELETE 避免 WAL 句柄延迟
- 路由 handler 测试改用 createMigratedMemoryTestDatabase 避免 File DB 锁
- SQLite 聚焦 --rerun-each=20 全部通过(720 pass)

后端测试补强
- 新增 tests/server/app.test.ts 真实 startServer 集成测试
- 覆盖 /api/meta、项目 CRUD、错误路径、静态 fallback、安全 header
- bootstrap/logger 测试捕获预期输出,消除测试噪音

前端测试补强
- 移除 .ant-* 内部类名依赖,改为角色/文本/导航/请求契约断言
- 项目页补充搜索、Tab 切换、表单、表格操作、错误反馈行为测试
- 新增 hooks(use-theme-preference、use-sidebar-collapsed、use-projects)纯逻辑测试
- 新增 ErrorBoundary 错误展示和刷新按钮测试
- 新增搜索清空行为测试
- 测试 setup 过滤 antd/rc-trigger NaN height warning

产品修复(测试暴露)
- 修复 ProjectToolbar 搜索框无法输入(新增 draftKeyword 状态)
- 加固 ProjectFormModal 表单字段同步(useEffect 替代不可靠的 afterOpenChange)
- 清理 ProjectFormModal 冗余 afterOpenChange 同步逻辑

重构与合规
- ProjectContext 拆分为三文件满足 React Fast Refresh 规则
- use-projects.ts 导出内部 helper 函数供测试验证
- scripts/build.ts 提取纯生成函数供测试使用,修复构建步骤日志编号
- 修复 build 测试覆盖真实生成逻辑

文档同步
- 更新后端/前端/开发文档测试规范、质量门禁和 helper 使用说明
2026-05-29 00:45:21 +08:00

132 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 后端开发
本文档说明 alfred 后端的 API、配置加载、日志、版本管理和后端测试开发约定。
适用场景:修改 src/server/、src/shared/api.ts、后端测试、配置契约、API 响应或日志模块。
## 库使用优先级
| 优先级 | 来源 | 典型用途 |
| ------ | ------------ | ---------------------------------------------------- |
| 1 | Bun 内置 API | Bun.serve、Bun.file、Bun.YAML、Bun.spawn、bun:sqlite |
| 2 | es-toolkit | 类型判断、深度比较、并发控制 |
| 3 | 标准 Web API | Headers、fetch、AbortController |
| 4 | 主流三方库 | pino、@sinclair/typebox、ajv、drizzle-orm |
| 5 | 自行实现 | 仅在以上都无法满足时 |
新增依赖前必须先检查上述每一层是否已有可用方案。
## API 路由开发
路由文件位于 src/server/routes/,每个端点一个文件。路由通过 server.ts 的 Bun.serve({ routes }) 声明式注册。
新增路由步骤:
1. 在 src/server/routes/ 下创建 <name>.ts
2. 实现 handler 函数并 export
3. 在 server.ts 的 routes 对象中注册路径和 method handler
4. 在 tests/server/ 中添加对应测试
## 共享工具
helpers.ts 提供跨路由共用的响应工具:
- createApiError(error, status) — 构造 API 错误体
- createHeaders(mode, init) — 创建响应 Headers
- jsonResponse(body, options) — JSON 响应构造
middleware.ts 提供 API 参数校验函数:
- validateIdParam(idStr, mode) — 校验 ID 参数格式
- validatePagination(pageParam, pageSizeParam, mode) — 校验分页参数
- validateTimeRange(from, to, mode) — 校验时间范围参数
## 数据库
项目使用 SQLite 作为存储后端,通过 bun:sqlite + Drizzle ORM 实现类型安全的数据访问。
### schema 定义
`src/server/db/schema.ts` 使用 Drizzle ORM 定义表结构,列名使用 snake_caseTypeScript 类型使用 camelCaseDrizzle schema 负责映射。
### 数据库连接
`src/server/db/connection.ts``createDatabase(dataDir, logger)` 打开 `<dataDir>/alfred.db`,设置 PRAGMAforeign_keys=ON、journal_mode=WAL、busy_timeout=5000
### migration 机制
- 开发期:使用 `drizzle-kit generate` 从 TS schema 生成 SQL migration 文件到 `drizzle/` 目录
- 生产期:构建时将 `drizzle/*.sql` 嵌入可执行文件,启动时自动应用 pending migrations
- 每次 migration 前自动备份现有 DB 到 `<dataDir>/backups/alfred-<timestamp>.db`
- migration 在事务中执行,失败则回滚并停止启动
### 数据访问
`src/server/db/projects.ts` 提供项目数据访问函数,输入输出使用 `src/shared/api.ts` 的类型。函数内部使用 Drizzle query builder 包装 `bun:sqlite` Database。
## 类型规范
- 共享类型以 src/shared/api.ts 为唯一源头
- 应用常量以 src/shared/app.ts 为唯一源头
- 版本号以 package.json.version 为唯一源头
- 前端不得 import src/server/ 下的任何文件
- 严格联合类型优先于宽类型
## 配置契约
配置加载流程固定为unknown -> AuthoringConfig -> NormalizedConfig -> ValidatedConfig -> ServerConfig。
Ajv 保持严格拒绝模式allErrors: true、不启用类型强制转换、不注入默认值、不自动删除未知字段。
新增或修改配置字段时必须同步更新 TypeBox schema fragments、config.schema.json、测试和对应用户文档。
## 日志模块
后端运行时代码统一通过 Logger 接口输出日志,禁止直接使用 console.\*。
| 实现 | 用途 |
| --------------------- | ------------------------ |
| PinoLoggerWrapper | 生产运行时 |
| ConsoleFallbackLogger | 配置加载失败前的降级日志 |
| NoopLogger | 静默丢弃日志 |
| MemoryLogger | 测试替身 |
敏感信息会自动 redact authorization、cookie、password 等字段。
## 版本管理
项目使用 package.json.version 作为版本号唯一来源。
版本获取方式:
- 开发模式src/server/version.ts 运行时从 package.json 读取
- 生产模式scripts/build.ts 在构建时将版本号烘焙为字面量注入
版本升迁命令:
```bash
bun run version:patch # 升迁 patch 版本
bun run version:minor # 升迁 minor 版本
bun run version:major # 升迁 major 版本
bun run version:set # 显式设置版本号
```
## 后端测试
| 变更类型 | 测试重点 |
| ------------------ | --------------------------------- |
| API 路由 | tests/server/app.test.ts 集成行为 |
| 配置 schema | schema 导出、合法/非法配置 |
| helpers/middleware | 单元测试 |
后端测试约定:
- API 路由集成测试必须通过真实 `startServer` 覆盖路由注册、HTTP method、fallback、响应 header 和核心错误路径。
- SQLite 相关测试必须复用 `tests/helpers.ts` 中的测试数据库 helper不要在测试文件内分散实现临时目录清理或直接裸用 `rmSync(dir, { recursive: true })`
- DAO 和路由边界测试应优先使用真实 migration 初始化测试库,只有 migration 执行器单测可以使用最小 fake migration。
- logger/bootstrap 中预期的 fallback 输出必须在测试中捕获并断言,正常通过的测试不应污染 stdout/stderr。
## 更新触发条件
修改后端 API、共享类型、配置契约、日志模块、版本管理或后端测试规范时必须更新本文档。