refactor(data): merge DTO models into schemas
This commit is contained in:
@@ -12,7 +12,7 @@ description: Sync this Next.js frontend with backend API documentation
|
||||
当后端 API 新增、删除、字段结构调整、响应语义变化时,使用本 skill 更新:
|
||||
|
||||
- 网络层
|
||||
- schema / DTO
|
||||
- schema / 不可变数据类
|
||||
- repository
|
||||
- storage
|
||||
- XState store
|
||||
@@ -26,15 +26,14 @@ description: Sync this Next.js frontend with backend API documentation
|
||||
| --- | --- | --- |
|
||||
| API Path | `src/data/services/api/api_path.ts` | 统一维护接口路径 |
|
||||
| API Service | `src/data/services/api/*_api.ts` | 调用 `httpClient` 并解析响应 |
|
||||
| Schema | `src/data/schemas/<module>/*.ts` | Zod schema,负责防御性解析 |
|
||||
| DTO | `src/data/dto/<module>/*.ts` | DTO class,封装 `fromJson/toJson` |
|
||||
| Schema Model | `src/data/schemas/<module>/*.ts` | Zod schema 与不可变数据类,负责解析和序列化 |
|
||||
| Repository Interface | `src/data/repositories/interfaces/i*_repository.ts` | 仓库接口 |
|
||||
| Repository | `src/data/repositories/*_repository.ts` | 业务仓库实现 |
|
||||
| Storage | `src/data/storage/*` | 本地持久化 |
|
||||
| Store | `src/stores/<module>/*` | XState 状态机、actors、helpers、sync |
|
||||
| UI | `src/app/**` | Next.js app router UI |
|
||||
| Mock | `src/data/mock/<module>/**` | 模拟请求 / 响应数据 |
|
||||
| Tests | `**/__tests__/*.test.ts` | DTO、helper、machine transition 测试 |
|
||||
| Tests | `**/__tests__/*.test.ts` | schema model、helper、machine transition 测试 |
|
||||
|
||||
## 后端文档来源
|
||||
|
||||
@@ -108,7 +107,7 @@ src/data/services/api/api_path.ts
|
||||
static readonly userEntitlements = `${ApiPath._user}/entitlements`;
|
||||
```
|
||||
|
||||
### 4. 更新 Schema
|
||||
### 4. 更新 Schema Model
|
||||
|
||||
在对应模块下新增或修改:
|
||||
|
||||
@@ -123,6 +122,13 @@ src/data/schemas/<module>/*.ts
|
||||
- 输入类型用 `z.input<typeof Schema>`。
|
||||
- 对后端可能返回 `null` 的字段做防御性处理。
|
||||
- 不要在 schema 中写 UI 逻辑。
|
||||
- Schema 与对应不可变数据类必须定义在同一个文件中。
|
||||
- 数据类的 `declare readonly` 只声明业务代码直接访问的字段。
|
||||
- 后端返回但前端既不读取、也不透传的字段,不要加入 Schema。
|
||||
- 仅用于请求序列化、响应兼容或内部透传的字段保留在 Schema 中,不声明 class 属性。
|
||||
- 数据类统一使用 `from()`、`fromJson()`、`toJson()` 与 `Object.freeze(this)`。
|
||||
- 没有嵌套转换或自定义方法时,使用 `src/data/schemas/schema_model.ts` 的 `createSchemaModel()`。
|
||||
- 不要再创建独立的数据传输对象层。
|
||||
|
||||
示例:
|
||||
|
||||
@@ -134,36 +140,8 @@ export const XxxResponseSchema = z.object({
|
||||
|
||||
export type XxxResponseInput = z.input<typeof XxxResponseSchema>;
|
||||
export type XxxResponseData = z.output<typeof XxxResponseSchema>;
|
||||
```
|
||||
|
||||
### 5. 更新 DTO
|
||||
|
||||
在对应模块下新增或修改:
|
||||
|
||||
```text
|
||||
src/data/dto/<module>/*.ts
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- DTO class 的 `declare readonly` 只声明前端业务代码会直接访问的字段。
|
||||
- 不要因为后端响应包含某字段,就机械地为它增加 class 属性、嵌套类型或类型别名。
|
||||
- 后端返回但前端既不读取、也不透传的字段,可以不加入 schema 和 DTO。
|
||||
- 仅用于请求序列化、响应兼容或内部透传的字段保留在 schema 中,不添加 class 属性声明。
|
||||
- `Object.assign(this, data)` 会保留 schema 解析后的字段;即使 class 未声明对应属性,`toJson()` 仍可按 schema 正常序列化。
|
||||
- 新增 DTO 字段前先搜索实际调用点;没有直接读取方时默认不声明。
|
||||
|
||||
DTO 统一模式:
|
||||
|
||||
```ts
|
||||
export const XxxResponseSchema = z.object({
|
||||
id: z.string(),
|
||||
// 仅用于内部透传,不需要在 DTO class 中声明。
|
||||
traceId: z.string(),
|
||||
});
|
||||
|
||||
export class XxxResponse {
|
||||
// 业务代码直接读取的字段才公开声明。
|
||||
declare readonly id: string;
|
||||
|
||||
private constructor(input: XxxResponseInput) {
|
||||
@@ -186,7 +164,7 @@ export class XxxResponse {
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 更新 API Service
|
||||
### 5. 更新 API Service
|
||||
|
||||
修改:
|
||||
|
||||
@@ -210,7 +188,7 @@ return XxxResponse.fromJson(unwrap(env) as Record<string, unknown>);
|
||||
- 不要在 API 层处理 UI 行为。
|
||||
- multipart 仍使用 `FormData`。
|
||||
|
||||
### 7. 更新 Repository
|
||||
### 6. 更新 Repository
|
||||
|
||||
修改:
|
||||
|
||||
@@ -229,14 +207,14 @@ async getXxx(): Promise<Result<XxxResponse>> {
|
||||
|
||||
Repository 可以做轻量编排,例如:
|
||||
|
||||
- request DTO 构造
|
||||
- request 数据类构造
|
||||
- 多接口组合
|
||||
- 本地 storage 同步
|
||||
- local model 与 DTO 转换
|
||||
- 本地模型与接口模型转换
|
||||
|
||||
不要把 React / UI 逻辑放进 repository。
|
||||
|
||||
### 8. 更新 Storage
|
||||
### 7. 更新 Storage
|
||||
|
||||
如果接口影响本地持久化,修改:
|
||||
|
||||
@@ -262,7 +240,7 @@ getEntitlementSnapshot(): Promise<Result<UserEntitlementSnapshotData | null>> {
|
||||
}
|
||||
```
|
||||
|
||||
### 9. 更新 Store / 状态机
|
||||
### 8. 更新 Store / 状态机
|
||||
|
||||
如果接口影响状态流,修改:
|
||||
|
||||
@@ -284,7 +262,7 @@ src/stores/<module>/*-sync.tsx
|
||||
- 页面组件不承担全局监听职责。
|
||||
- 状态机事件应表达业务事实,而不是 UI 操作细节。
|
||||
|
||||
### 10. 更新 UI
|
||||
### 9. 更新 UI
|
||||
|
||||
只有在接口变更影响展示或用户明确要求时,才修改:
|
||||
|
||||
@@ -298,19 +276,18 @@ src/app/**
|
||||
- 不在页面组件里直接写复杂业务编排。
|
||||
- 全局监听逻辑优先放到 `stores/*/*-sync.tsx`。
|
||||
|
||||
### 11. 更新桶文件
|
||||
### 10. 更新桶文件
|
||||
|
||||
如果新增 schema / DTO / component,更新对应 `index.ts`:
|
||||
如果新增 schema model 或 component,更新对应 `index.ts`:
|
||||
|
||||
```text
|
||||
src/data/schemas/<module>/index.ts
|
||||
src/data/dto/<module>/index.ts
|
||||
src/app/**/components/index.ts
|
||||
```
|
||||
|
||||
如果项目使用 barrelsby 生成,不要手动破坏现有导出格式。
|
||||
|
||||
### 12. 更新 Mock 数据
|
||||
### 11. 更新 Mock 数据
|
||||
|
||||
如果新增或调整数据结构,按一个结构一个文件的原则放到:
|
||||
|
||||
@@ -322,11 +299,11 @@ src/data/mock/<module>/websocket-events
|
||||
|
||||
不要把多个结构塞进一个大 JSON。
|
||||
|
||||
### 13. 更新测试
|
||||
### 12. 更新测试
|
||||
|
||||
优先补充:
|
||||
|
||||
- DTO / schema parse 测试
|
||||
- schema model 解析与序列化测试
|
||||
- helper 纯函数测试
|
||||
- XState transition 测试
|
||||
- repository 编排测试(如已有测试基础)
|
||||
@@ -334,11 +311,11 @@ src/data/mock/<module>/websocket-events
|
||||
常见位置:
|
||||
|
||||
```text
|
||||
src/data/dto/<module>/__tests__/*.test.ts
|
||||
src/data/schemas/<module>/__tests__/*.test.ts
|
||||
src/stores/<module>/__tests__/*.test.ts
|
||||
```
|
||||
|
||||
### 14. 验证
|
||||
### 13. 验证
|
||||
|
||||
至少运行:
|
||||
|
||||
@@ -356,18 +333,17 @@ pnpm exec vitest run <related tests>
|
||||
|
||||
1. 文档确认 path / method / payload。
|
||||
2. `api_path.ts` 新增路径。
|
||||
3. 新增 schema。
|
||||
4. 新增 DTO。
|
||||
5. API service 新增方法。
|
||||
6. repository interface + implementation 新增方法。
|
||||
7. 如需要,接入 store actor / event。
|
||||
8. 补 mock 和测试。
|
||||
9. 运行验证。
|
||||
3. 在同一文件新增 schema 与不可变数据类。
|
||||
4. API service 新增方法。
|
||||
5. repository interface + implementation 新增方法。
|
||||
6. 如需要,接入 store actor / event。
|
||||
7. 补 mock 和测试。
|
||||
8. 运行验证。
|
||||
|
||||
### 修改响应字段
|
||||
|
||||
1. 更新 schema。
|
||||
2. 更新 DTO declare 字段和 `toJson`。
|
||||
2. 更新同文件数据类的公开字段和 `toJson`。
|
||||
3. 更新 mapper/helper。
|
||||
4. 更新 UI 或状态机依赖字段。
|
||||
5. 更新 mock 和测试。
|
||||
@@ -377,7 +353,7 @@ pnpm exec vitest run <related tests>
|
||||
|
||||
1. 搜索所有引用。
|
||||
2. 删除 API path / API method / repository method。
|
||||
3. 删除 DTO/schema/mock/test。
|
||||
3. 删除 schema model、mock 和测试。
|
||||
4. 更新状态机和 UI 调用。
|
||||
5. 运行 `rg` 确认无残留引用。
|
||||
6. 运行验证。
|
||||
|
||||
Reference in New Issue
Block a user