contracts-in-dailyuse
contracts-in-dailyuse
#resource / typescript
#type / howto
#status / growing
[!info] related notes
- 所属 MOC: 后端开发 MOC
- 前置概念: 接口规范, 前后端的DTO数据同步
- 相关实践: nodejs后端api测试搭建集成测试框架, 契约测试与 CDC
- 相关项目: Daily Use MOC
contracts-in-dailyuse
前置知识
- contract first
- DDD
src
├── modules // 模块的类型定义
├── shared // 共享的类型定义
├── response // api响应的类型定义
└── index.ts
modules 的类型定义
modules
└── goal
├── dtos.ts
├── enums.ts
├── events.ts
├── index.ts
├── persistence-dtos.ts
└── types.ts
types.ts
该文件是一个模块的开始:
- 实体的接口定义(服务端的+客户端的,是不是可以加个 core?)
- 实体属性类型定义
- 常量定义
/**
* 目标接口 实体的接口定义
*/
export interface IGoal {
uuid: string;
dirUuid?: string;
name: string;
metadata: {
tags: string[];
category: string;
};
}
/**
* 目标统计接口 实体属性类型定义
*/
export interface IGoalStats {
totalGoals: number;
activeGoals: number;
}
/**
* 系统默认文件夹配置 常量定义
*/
export const SYSTEM_GOAL_DIRS = {
ALL: {
uuid: 'system_all',
name: '全部目标',
icon: 'mdi-folder-multiple',
color: '#2196f3',
},
DELETED: {
uuid: 'system_deleted',
name: '已删除',
icon: 'mdi-delete',
color: '#f44336',
},
ARCHIVED: {
uuid: 'system_archived',
name: '已归档',
icon: 'mdi-archive',
color: '#9e9e9e',
},
} as const;
enums.ts
枚举类型
/**
* 目标状态枚举
*/
export enum GoalStatus {
ACTIVE = 'active',
COMPLETED = 'completed',
PAUSED = 'paused',
ARCHIVED = 'archived',
}
persistence-dto.ts
仓储层的类型定义,将实体对象存储到数据库中(toPersistence)使用
- 扁平化
- 类型转换
/**
* 目标持久化 DTO
*/
export interface GoalPersistenceDTO {
uuid: string;
accountUuid: string;
// 基本信息
name: string;
description?: string;
color: string;
dirUuid?: string;
startTime: Date; // PostgreSQL TIMESTAMP WITH TIME ZONE
endTime: Date; // PostgreSQL TIMESTAMP WITH TIME ZONE
note?: string;
// 分析信息 - 扁平化
motive: string;
feasibility: string;
importanceLevel: ImportanceLevel;
urgencyLevel: UrgencyLevel;
// 生命周期
createdAt: Date;
updatedAt: Date;
status: GoalStatus;
// 元数据 - JSON 存储
tags: string; // JSON string
category: string;
// 版本控制
version: number;
}
dtos.ts
- 实体(服务端)的DTO形态(感觉也可以提取出去)
- 前后端请求响应的类型定义 crud 接口中也一般是和实体DTO相关,直接扩展
- 实体(客户端)的DTO形态 一般是服务端DTO加几个计算属性,所以直接扩展
/** 实体(服务端)的DTO形态(感觉也可以提取出去)
* 目标 DTO - 服务端数据传输对象
* 用于服务端内部传输(Repository <-> Application <-> Domain)
*/
export interface GoalDTO {
uuid: string;
name: string;
description?: string;
color: string;
dirUuid?: string;
startTime: number;
endTime: number;
note?: string;
analysis: {
motive: string;
feasibility: string;
importanceLevel: ImportanceLevel;
urgencyLevel: UrgencyLevel;
};
lifecycle: {
createdAt: number;
updatedAt: number;
status: GoalStatus;
};
metadata: {
tags: string[];
category: string;
};
version: number;
// 关联的子实体
keyResults?: KeyResultDTO[];
records?: GoalRecordDTO[];
reviews?: GoalReviewDTO[];
}
/** 前后端请求响应的类型定义
* 创建目标请求 - POST /api/v1/goals
* 前端生成 uuid,后端直接转为实体持久化
*/
export type CreateGoalRequest = Pick<
GoalDTO,
'uuid' | 'name' | 'color' | 'startTime' | 'endTime' | 'analysis' | 'metadata'
> & {
description?: string;
dirUuid?: string;
note?: string;
// 创建时可以一起创建子实体
keyResults?: CreateKeyResultRequest[];
records?: CreateGoalRecordRequest[];
reviews?: CreateGoalReviewRequest[];
};
/** 实体(客户端)的DTO形态
* 目标目录客户端 DTO - 前端渲染对象
*/
export interface GoalDirClientDTO extends GoalDirDTO {
// 计算属性
goalsCount: number; // 目录下的目标数量
subDirs?: GoalDirClientDTO[]; // 子目录列表
}