Files
wwjcloud-nest-v1/docs/DEVELOPMENT-GUIDE.md
wanwu b735e24428 fix: 修复service模块重命名逻辑并成功集成core层API
主要修改:
1. 修复module-generator中服务重命名时的DI错误
   - 对于重命名的服务,直接使用别名注册,避免TypeScript找不到原始名称
   - 移除不必要的provide/useClass模式

2. 集成core层到主应用
   - 在app.module.ts中导入wwjcloud-core的AppModule
   - 在wwjcloud-core/src/index.ts中导出AppModule

3. 构建结果
   - 编译错误: 64+ -> 0
   - 注册路由: 15 -> 678
   - Docker服务全部正常启动
   - API接口正常响应
2025-10-26 20:40:23 +08:00

9.6 KiB
Raw Blame History

WWJCloud NestJS 开发指导原则

基于 v0.1.1 版本真实项目结构分析制定
更新时间: 2025-01-27
适用范围: WWJCloud NestJS 项目开发

🎯 核心开发原则

1. 框架使用原则

  • 框架层面: 100% 使用 NestJS 的方式和特性
  • 业务层面: 与 Java 项目保持 100% 一致
  • 数据层面: 与 Java 项目数据库结构 100% 一致

2. 开发约束条件

  • 必须: 基于 Java 项目真实代码进行开发
  • 必须: 基于真实数据库表结构进行映射
  • 必须: 遵循项目既定的命名规范
  • 禁止: 自创业务逻辑或数据结构
  • 禁止: 编写骨架代码或 TODO 注释
  • 禁止: 硬编码业务数据或配置

📁 项目结构规范

目录层级

src/
├── config/                 # 配置管理层
│   ├── *.config.ts         # 各类配置文件
│   ├── config.module.ts    # 配置模块
│   └── *.entity.ts         # 配置相关实体
├── common/                 # 通用服务层
│   ├── base/               # 基础服务
│   ├── utils/              # 工具类
│   ├── interceptors/       # 拦截器
│   ├── guards/             # 守卫
│   └── pipes/              # 管道
├── core/                   # 核心基础设施层
│   └── (待开发)
└── vendor/                 # 第三方服务适配层
    ├── pay/                # 支付服务
    ├── sms/                # 短信服务
    └── upload/             # 上传服务

🏷️ 命名规范标准

文件命名规范

1. 实体文件

  • 格式: kebab-case.entity.ts
  • 示例: dynamic-config.entity.ts, sys-user.entity.ts
  • 说明: 使用短横线分隔,以 .entity.ts 结尾

2. 服务文件

  • 格式: kebab-case.service.ts
  • 示例: config-center.service.ts, pay.service.ts
  • 说明: 使用短横线分隔,以 .service.ts 结尾

3. 控制器文件

  • 格式: kebab-case.controller.ts
  • 示例: config-center.controller.ts, auth.controller.ts
  • 说明: 使用短横线分隔,以 .controller.ts 结尾

4. 工具类文件

  • 格式: kebab-case.util.ts
  • 示例: json.util.ts, string.util.ts
  • 说明: 使用短横线分隔,以 .util.ts 结尾

5. 模块文件

  • 格式: kebab-case.module.ts
  • 示例: config.module.ts, auth.module.ts
  • 说明: 使用短横线分隔,以 .module.ts 结尾

6. DTO 文件

  • 格式: PascalCaseDto.ts
  • 示例: CreateUserDto.ts, UpdateConfigDto.ts
  • 说明: 使用 PascalCaseDto.ts 结尾

类命名规范

1. 实体类

  • 格式: PascalCase
  • 示例: DynamicConfig, SysUser, MemberLevel
  • 说明: 与数据库表名对应,使用 PascalCase

2. 服务类

  • 格式: PascalCase + Service
  • 示例: ConfigCenterService, PayService, AuthService
  • 说明: 业务名称 + Service 后缀

3. 控制器类

  • 格式: PascalCase + Controller
  • 示例: ConfigCenterController, AuthController
  • 说明: 业务名称 + Controller 后缀

4. 工具类

  • 格式: PascalCase + Util
  • 示例: JsonUtil, StringUtil, DateUtil
  • 说明: 功能名称 + Util 后缀

5. DTO 类

  • 格式: 操作动词 + 业务名称 + Dto
  • 示例: CreateUserDto, UpdateConfigDto, QueryMemberDto
  • 说明: 明确表示操作类型和业务对象

方法命名规范

1. 业务方法

  • 格式: camelCase
  • 原则: 与 Java 项目方法名保持一致
  • 示例: getUserList(), addUser(), updateConfig()

2. 私有方法

  • 格式: camelCase
  • 示例: private validateUser(), private formatData()

3. 生命周期方法

  • 格式: 按 NestJS 标准
  • 示例: onModuleInit(), onApplicationBootstrap()

变量命名规范

1. 私有属性

  • 格式: private readonly camelCase
  • 示例: private readonly logger, private readonly configService

2. 业务变量

  • 格式: camelCase
  • 原则: 与 Java 项目变量名保持一致
  • 示例: userId, userName, configKey

3. 常量

  • 格式: UPPER_SNAKE_CASE
  • 示例: DEFAULT_PAGE_SIZE, MAX_RETRY_COUNT

数据库相关命名

1. 表名映射

  • 原则: 与 Java 项目表名 100% 一致
  • 示例: nc_sys_config, nc_sys_user, nc_member_level
  • 说明: 不能修改任何表名或前缀

2. 字段名映射

  • 原则: 与 Java 项目字段名 100% 一致
  • 示例: site_id, config_key, create_time, update_time
  • 说明: 不能修改任何字段名或类型

🔧 开发最佳实践

Nest DI 与导入规范(重要)

  • DI 相关类(如 MetricsServiceCacheServiceLockService)统一使用深路径导入:@wwjcloud/wwjcloud-boot/infra/...
  • 禁止在 AI 模块中通过聚合路径 @wwjcloud/wwjcloud-boot 导入上述 DI 类,避免符号不一致导致依赖解析失败。
  • 优先使用“按类型注入”,仅在确有抽象需要时使用令牌,并确保令牌在提供方模块中唯一、稳定导出。
  • 避免在运行期使用 ModuleRef.get 动态解析,除非处理循环依赖或跨域解耦的极端场景。
  • 约定Boot 层模块负责提供与导出,业务模块仅按类型消费,不再重复定义别名提供者。

1. 依赖注入

@Injectable()
export class UserService {
  constructor(
    private readonly userRepository: Repository<User>,
    private readonly configService: ConfigService,
    private readonly logger: Logger,
  ) {}
}

2. 装饰器使用

@Controller('api/user')
@UseGuards(JwtAuthGuard)
export class UserController {
  @Get('list')
  @UseInterceptors(ResponseInterceptor)
  async getUserList(@Query() query: QueryUserDto) {
    // 实现逻辑
  }
}

3. 异常处理

@Injectable()
export class UserService {
  async findUser(id: number) {
    const user = await this.userRepository.findOne({ where: { id } });
    if (!user) {
      throw new NotFoundException('用户不存在');
    }
    return user;
  }
}

4. 数据验证

export class CreateUserDto {
  @IsString()
  @IsNotEmpty()
  username: string;

  @IsEmail()
  email: string;

  @IsOptional()
  @IsString()
  nickname?: string;
}

📋 开发检查清单

开发前检查

  • 已查看对应的 Java 源码文件
  • 已查看相关的数据库表结构
  • 已理解真实的业务逻辑
  • 已确认所有依赖关系

开发中检查

  • 文件命名符合项目规范
  • 类命名符合项目规范
  • 方法命名与 Java 项目一致
  • 数据库字段映射准确
  • 业务逻辑与 Java 项目一致

开发后检查

  • 代码可以正常编译
  • 所有依赖正确注入
  • 数据库操作正常
  • API 接口功能正确
  • 异常处理完善

🚫 常见错误避免

1. 命名错误

  • 错误: userController.ts (camelCase)
  • 正确: user.controller.ts (kebab-case)

2. 文件结构错误

  • 错误: 按技术层级划分目录
  • 正确: 按业务模块划分目录

3. 业务逻辑错误

  • 错误: 自创业务逻辑
  • 正确: 基于 Java 项目真实代码

4. 数据库映射错误

  • 错误: 修改表名或字段名
  • 正确: 与 Java 项目 100% 一致

📚 参考资源


本文档基于项目真实结构制定,请严格遵循以确保代码质量和项目一致性。

🔧 AI 恢复模块集成与测试

模块挂载

  • 根应用:AI_ENABLED=true 时动态导入 AiModule
  • apps/api:直接导入 AiModule,受 GLOBAL_PREFIX=api 影响
  • 开发阶段:AiController 使用 @Public() 便于无令牌验证;生产需加守卫或网关策略

路由与前缀

  • 推荐统一使用 GLOBAL_PREFIX=api 以避免基础设施路由状态码异常
  • 端点示例:
    • GET /api/ai/recovery/status
    • GET /api/ai/recovery/simulate-failure?taskId=T1&severity=high&reason=dev
    • POST /api/ai/recovery/process-one
    • POST /api/ai/recovery/drain

队列驱动策略

  • 开发:QUEUE_DRIVER=memory,避免 Kafka/Redis 干扰,快速闭环
  • 生产:推荐 redis 或企业内部 kafka,实现跨进程/跨实例协同

依赖注入规范(与 DI 章节一致)

  • Boot 层 DI 使用深路径导入:@wwjcloud/wwjcloud-boot/infra/...
  • 业务模块按类型消费,避免重复定义令牌与别名
  • 事件监听器与服务在 AiModule 内提供并导出:AiSelfHealListenerAiRecoveryService

本地端到端验证

# 查看初始队列大小
curl -s http://localhost:3001/api/ai/recovery/status
# 模拟失败(入队)
curl -s "http://localhost:3001/api/ai/recovery/simulate-failure?taskId=T1&severity=high&reason=dev"
# 再次查看(应增长)
curl -s http://localhost:3001/api/ai/recovery/status
# 处理一个(收敛)
curl -s -X POST http://localhost:3001/api/ai/recovery/process-one
# 清空队列(可选)
curl -s -X POST http://localhost:3001/api/ai/recovery/drain

测试建议

  • e2e覆盖失败事件触发 → 入队 → 处理 → 收敛的闭环
  • 异常过滤:GLOBAL_PREFIX=api/api/metrics/api/health 保留原始状态码
  • 队列驱动兼容:memoryrediskafka 三模式最小用例

参考

  • 详细指南:docs/AI-RECOVERY-DEV.md
  • 工作流规范:docs/AI-WORKFLOW-GUIDE.md