跳到主要内容

目录规范

总体结构​

realtime-service/
├── src/
│ ├── common/ # 跨模块共享能力
│ │ ├── decorators/ # 自定义装饰器(@CurrentUser() 等)
│ │ ├── filters/ # 全局异常过滤器
│ │ ├── guards/ # 全局守卫(JwtAuthGuard、RolesGuard)
│ │ ├── interceptors/ # 全局拦截器(日志、响应包装)
│ │ ├── pipes/ # 全局管道
│ │ └── utils/ # 纯函数工具(不含业务语义)
│ ├── config/ # 配置模块(环境变量校验、命名空间配置)
│ ├── infra/ # 基础设施模块
│ │ ├── redis/ # Redis 客户端与缓存服务
│ │ ├── kafka/ # Kafka 生产者/消费者封装
│ │ └── spring/ # Spring 下游服务 HTTP 客户端封装
│ ├── modules/ # 业务模块(按业务域划分)
│ │ ├── notification/ # 通知域
│ │ │ ├── dto/ # 请求/响应 DTO(class-validator)
│ │ │ ├── notification.gateway.ts
│ │ │ ├── notification.resolver.ts
│ │ │ ├── notification.controller.ts
│ │ │ ├── notification.service.ts
│ │ │ ├── notification.module.ts
│ │ │ └── index.ts # 统一导出
│ │ └── dashboard/ # 聚合查询域
│ │ ├── dto/
│ │ ├── dashboard.resolver.ts
│ │ ├── dashboard.service.ts
│ │ ├── dashboard.module.ts
│ │ └── index.ts
│ ├── app.module.ts # 根模块
│ └── main.ts # 入口(Fastify 引导)
├── test/ # E2E 测试
├── .env.development # 环境变量(不提交真实密钥)
├── nest-cli.json
├── package.json
├── tsconfig.json
└── tsconfig.build.json

分层约定​

目录职责依赖规则
modules/业务域模块:gateway / resolver / controller / service只允许依赖 infra/、common/ 与自身模块内部文件
infra/基础设施:下游 HTTP 客户端、消息队列、缓存只允许依赖 config/、common/,禁止依赖 modules/
config/环境变量加载与校验不依赖任何业务目录
common/横切组件与纯函数不依赖任何业务目录

单向依赖:modules/ → infra/ → config/,禁止反向引用。

避免教条化

单一职责的小服务(仅一个业务域)可直接在 src/ 下平铺模块,不必强行套 modules/ 目录。分层是按需收口,不是所有项目都必须完整目录树。

模块内部约定​

  • 每个业务域一个目录,目录名为单数小写连字符(notification、dashboard、device-status)
  • 文件命名遵循 NestJS 约定:{域名}.{角色}.ts,角色 ∈ controller / gateway / resolver / service / module / dto
  • 每个模块目录提供 index.ts 统一导出,使用方不深入内部路径
// modules/notification/index.ts
export { NotificationModule } from './notification.module';
export { NotificationService } from './notification.service';
// 推荐:从统一入口导入
import { NotificationService } from '@/modules/notification';

// 反例:深入内部路径
import { NotificationService } from '@/modules/notification/notification.service';

DTO 约定​

  • 请求 DTO 与响应 DTO 分文件存放于 dto/ 目录:create-notification.request.ts、notification.payload.ts
  • 所有入口参数(REST Body / WS Message / GraphQL Input)必须有对应 DTO,并使用 class-validator 装饰器声明校验规则
  • GraphQL Code First 的 ObjectType / InputType 与 DTO 复用同一类,避免重复定义
// modules/notification/dto/subscribe-topic.dto.ts
import { IsIn, IsNotEmpty, IsString } from 'class-validator';
import { Field, InputType } from '@nestjs/graphql';

@InputType()
export class SubscribeTopicDto {
@Field()
@IsString()
@IsNotEmpty()
topic: string;

@Field()
@IsIn(['user', 'tenant', 'broadcast'])
scope: 'user' | 'tenant' | 'broadcast';
}