7.7 KiB
7.7 KiB
Nestjs 项目下的规范 [JsTs.Nest]
- includes
*.controller.ts*.service.ts*.module.ts*.dto.ts*.pipe.ts*.guard.ts*.interceptor.ts*.filter.ts*.exception-filter.ts*.proxy.ts*.model.ts*.constants.ts- override
[JsTs.FileName]
目录框架规范 [JsTs.Nest.DirStructure]
- 使用下面的 Good 目录结构
- 文件名使用小写加横线命名(如
user-extends.module.ts) - 每个模块的目录下必须包含
module.ts文件 - 每个模块的目录下必须包含
controller.ts文件 - 每个模块的目录下必须包含
service.ts文件 - 每个模块的目录下可以包含
dto目录,用于存放数据传输对象 - 每个模块的目录下可以包含
pipe目录,用于存放管道 - 每个模块的目录下可以包含
guard目录,用于存放守卫 - 每个模块的目录下可以包含
interceptor目录,用于存放拦截器 - 每个模块的目录下可以包含
filter目录,用于存放异常过滤器
Example: 目录结构
Good: 按模块组织的目录结构
src/
├── user/ # 用户模块
│ ├── user.module.ts
│ ├── user.controller.ts
│ ├── user.service.ts
│ ├── user.proxy.ts
│ ├── user.model.ts
│ └── dto/ # 数据传输对象
├── auth/ # 认证模块
│ ├── auth.module.ts
│ ├── auth.controller.ts
│ ├── auth.service.ts
│ ├── auth.proxy.ts
│ ├── auth.model.ts
├── common/ # 公共模块
│ ├── filters/ # 异常过滤器
│ ├── guards/ # 守卫
│ ├── interceptors/ # 拦截器
│ └── pipes/ # 管道
├── config/ # 配置文件
├── app.module.ts # 根模块
└── main.ts # 应用入口
Bad: 扁平化的目录结构
src/
├── user.controller.ts
├── user.service.ts
├── auth.controller.ts
├── auth.service.ts
├── filter.ts
├── guard.ts
└── main.ts
控制器命名规范 [JsTs.Nest.ControllerDefinition]
- 该文件不能写业务逻辑,只能写调用 service 的代码
- 文件名使用小写加横线命名(如
user-extends.controller.ts) - 文件名必须加
.controller.ts后缀 - 注解和装饰器上的静态值无需进行魔法值的提炼
[JsTs.Base.NoMagicStringsAndNumbers]
Example: 控制器文件命名
Good: 使用小写加横线命名
user-extends.controller.ts
Bad: 使用大驼峰命名
userController.ts
服务命名规范 [JsTs.Nest.ServiceDefinition]
- 这个是目前业务代码核心编写的地方
- 规定不能直接调用数据库查询,只能通过 model 来调用
- 规定不能直接调用旧的业务代码,只能通过 proxy 来调用
- 文件名使用小写加横线命名(如
user-extends.service.ts) - 文件名必须加
.service.ts后缀
Example: 服务文件命名
Good: 使用小写加横线命名
user-extends.service.ts
Bad: 使用大驼峰命名
userService.ts
模块命名规范 [JsTs.Nest.ModuleDefinition]
- 文件名使用小写加横线命名(如
user-extends.module.ts) - 文件名必须加
.module.ts后缀
Example: 模块文件命名
Good: 使用小写加横线命名
user-extends.module.ts
Bad: 使用大驼峰命名
userModule.ts
Dto 命名规范 [JsTs.Nest.DtoDefinition]
- override
[JsTs.Base.NoMagicStringsAndNumbers]
- 文件名使用小写加横线命名(如
user-extends.dto.ts) - 文件名必须加
.dto.ts后缀 - dto 目录下必须包含
dto.ts文件 - dto 里的类的属性可以使用小驼峰或者下划线命名
Example: Dto 文件命名
Good: 使用小写加横线命名
user-extends.dto.ts
Bad: 使用大驼峰命名
userDto.ts
Proxy 编写规范 [JsTs.Nest.ProxyDefinition]
- 这是专门为了和旧的业务通讯而存在的和旧代码通讯使用的方式就是 SyncService
- 文件名使用小写加横线命名(如
user.proxy.ts) - 文件名必须加
.proxy.ts后缀 - 内部只能写使用 syncService 调用的逻辑
- SyncService 只能在 proxy.ts 中使用
Example: Proxy 编写
Good: Proxy 只使用 SyncService 调用旧业务
// user.proxy.ts
import { Injectable } from "@nestjs/common";
import { User } from "@app/entity/models";
import { SyncService } from "@app/sync";
@Injectable()
export class UserProxy {
constructor(private readonly syncService: SyncService) {}
getUsersByNames(names: string[], callback: (user: User) => void) {
return this.syncService.call("userProxy").getUsersByNames(names, callback);
}
}
Bad: Proxy 中直接查询数据库
// user.proxy.ts
import { Injectable } from "@nestjs/common";
import { User } from "@app/entity/models";
import { InjectModel } from "@app/entity/decorator";
import { Model } from "mongoose";
@Injectable()
export class UserProxy {
constructor(@InjectModel(User) private readonly userModel: Model<User>) {}
getUsersByNames(names: string[], callback: (user: User) => void) {
return this.userModel.find({ name: { $in: names } }, callback);
// 不能写数据库查询,只能写和旧的业务通讯代码,数据库查询的逻辑要放在 user.model.ts
}
}
Model 编写规范 [JsTs.Nest.ModelDefinition]
- includes
*.model.ts
- 内部只能写使用 model 数据库调用的逻辑
- 文件名使用小写加横线命名(如
user.model.ts) - 文件名必须加
.model.ts后缀
Example: Model 编写
Good: Model 只使用数据库调用
// user.model.ts
import { Injectable } from "@nestjs/common";
import { User } from "@app/entity/models";
import { InjectModel } from "@app/entity/decorator";
import { Model } from "mongoose";
@Injectable()
export class UserProxy {
constructor(@InjectModel(User) private readonly userModel: Model<User>) {}
getUsersByNames(names: string[], callback: (user: User) => void) {
return this.userModel.find({ name: { $in: names } }, callback);
}
}
Bad: Model 中使用 SyncService 调用旧业务
// user.model.ts
import { Injectable } from "@nestjs/common";
import { User } from "@app/entity/models";
import { SyncService } from "@app/sync";
@Injectable()
export class UserProxy {
constructor(private readonly syncService: SyncService) {}
getUsersByNames(names: string[], callback: (user: User) => void) {
return this.syncService.call("userProxy").getUsersByNames(names, callback);
// 不能写和旧的业务通讯代码,只能写数据库查询的逻辑,和旧的业务通讯的代码要放在 proxy.ts 中
}
}
业务代码编写规范 [JsTs.Nest.BusinessDefinition]
- 目前所有的新代码都应该写在 nest 里
Example: 业务代码位置
Good: 新代码写在 nest 目录下
// nest-src/apps/app/src/user/user.controller.ts
// nest-src/apps/app/src/user/user.service.ts
// nest-src/apps/app/src/user/user.module.ts
Bad: 新代码写在旧目录下
// proxy/user.js
基于 JsTs.Base.NoMagicStringsAndNumbers 抽离的静态常量需要放在对应文件里 [JsTs.Nest.ConstantsDefinition]
- severity
warn- override
[JsTs.Base.ConstantsDefinition]
- 需要放在指定模块的 constants 文件里
Example: 常量定义位置
Good: 常量放在对应模块的 constants 文件
// user.constants.ts
const MAX_COUNT = 100; // 这是 user 模块需要的
Bad: 常量放在错误模块的 constants 文件
// class.constants.ts
const MAX_COUNT = 100; // 这是 user 模块需要的