主要技术栈: Nest + Fastify + Prisma + mysql + TypeScript
- 快速 CRUD:查看文档,快速生成 crud 模块(只需定义 prisma 数据模型,便可生成 module、controller、service、dto 文件,有新增、单个查询、查询全部、分页查询、更新、批量删除、批量恢复等接口);
- OpenAPI/Swagger 文档
- 统一异常于响应处理
- 单元测试: 查看文档 ;
- file 文件上传/下载:上传到本地或OSS,生成文件预览地址;
- 消息队列:使用 BullMQ 平滑处理高峰、分解可能阻塞Node.js事件循环的整体任务、在各种服务之间提供可靠的通信渠道;
- 缓存:使用 ioredis;
- 短信/邮件发送:使用消息队列;
- JWT身份验证
- 权限管理
- 日志:使用 winston 打印日志,保存在根目录 logs 文件夹;
- Docker 部署
Serverless 部署- Prisma文档生成器
- 我的开发环境是
node v18.17.0
、pnpm 8.14.1
、mysql 8
其他版本未测试;
在运行项目之前,需要修改配置文件
- 在
.env
文件里配置数据库连接; - 在
.env.development
文件里配置 Redis、OSS、EMAIL、SMS信息 (非必需); - 还可在
src/config/index.ts
文件里修改全局路由前缀、图片上传目录;
$ pnpm install
首次启动项目时,先按照下面的 prisma tips 步骤走。
# development
$ pnpm run start
# watch mode 开发时使用,可热重载
$ pnpm run start:dev
# production mode
$ pnpm run start:prod
项目运行后浏览器打开 http://localhost:3000/swagger#
查看api文档
登录后获取的 access_token 要在前面拼接 Bearer 使用,header格式为
{
Authorization: `Bearer ${access_token}`
}
- 首次启动前,先运行
npx prisma migrate dev --name "init"
将运行迁移脚本以在数据库中创建实体表。 - 然后运行
npx prisma db seed
命令来运行prisma/seed.ts
文件,在数据库里生成初始数据。 - 将来,你需要在每次更改 Prisma 模型后运行
npx prisma generate
命令以更新生成的 Prisma 客户端(即更新TS类型)。 - 如果后续要同步数据库,那么使用
npx prisma db pull
或者npx prisma db push
进行推送或拉取更新(如果在model里新增了非空字段且无默认值,那么push时会警告⚠️ ,需要使用--force-reset
忽略所有警告,⚠️ 危险操作,会清空数据) - push 和 pull 不会生成记录,如果要在
prisma/migrations
里生成记录,需要运行migrate dev
命令,
# 1.打包
$ pnpm run docker:build
# 2.构建镜像
$ docker build -t my-nest-app .
# 3.运行容器
$ docker run -itd -p 3000:3000 --name nestify-boot my-nest-app
# 若要将日志和上传图片挂载,那么可以使用 `-v` 参数来挂载日志和上传图片目录。
# $ docker run -itd -p 3000:3000 -v /path/to/logs:/app/logs -v /path/to/uploads:/nest-static --name nestify-boot my-nest-app
如果是本地运行,且使用宿主机上的 Redis 服务,那么需要修改
.env.development
文件里的REDIS_HOST
为host.docker.internal
来代替localhost
,以便连接到宿主机上的 Redis 服务(同时也要修改REDIS_URL
)。
使用@nestjs/swagger集成swagger功能。
SwaggerModule 在路由处理程序中搜索所有 @Body()、@Query() 和 @Param() 装饰器以生成 API 文档。它还通过利用反射创建相应的模型定义,我们主要的心智负担在 DTO 上定义属性,当然,这个也可以靠CLI插件帮助生成,或者使用 Github Copilot 来面向TAB编程。
项目运行后打开 http://localhost:3000/swagger#
查看web文档,也可在http://localhost:3000/swagger-json
查看json数据,导入到 Apifox 太方便了。
- 定义了自定义装饰器ApiPaginatedResponse,用于Swagger响应类型,但没有定义最外层的http响应类型装饰器,感觉没有必要,多处重复看起来杂乱,有TS类型就够了。
- swagger ui 里测试接口需要在右上角配置登录获取的token
- 在
/typings/response.d.ts
里定义了http响应的TS类型 - 在
src/common/interceptor/success-response.ts
为成功的Http响应数据统一添加 code、msg、success 字段。 - 在
src/common/interceptor/http-faild.ts
里定义了HttpException拦截器,拦截后返回统一的json格式,记录到日志。- 但它不会拦截 Prisma 的异常,关于Prisma异常,可以重新定义一个 @Catch(PrismaClientValidationError)的拦截器,或者在 service 层手动处理,查看官方文档:处理异常和错误
- class-validator 参数校验:用于dto的参数校验 https://www.npmjs.com/package/class-validator
-
在
class AuthGuard
中定义了全局守卫,如果要放开某些接口,使用自定义装饰器@Guest()
即可,参考auth/login
接口。未开放的接口需要在Header里传 Authorization,值为·
Bearer + 登录接口返回的token
; swagger ui 里运行需要在右上角配置,应该不用加上 Bearer 头; -
自定义参数装饰器,用于获取token解析后的用户信息,用法如下:
import { User, UserJwtType } from '@/common/decorator/user.decorator'
@Get('test')
test(@ReqUser('id') id: number, @ReqUser() user: UserJwtType) {
return {
id,
user: user,
}
}
目前没有设计refresh_token
给前端使用,我想不明白这么做的必要性,为了安全不如搞Https协议还有CORS和CSRF保护,避免XSS攻击等。唯一的作用可能是存到数据库后用来感知用户退出登录、切换账号操作。
使用二进制位运算进行权限管理,参考自权限控制 | 使用二进制做权限控制功能
在 permission.guard.ts
里定义了权限守卫,具体用法可参考auth.controller.ts
文件。
使用 vercel 部署这个项目遇到些问题,例如文件上传和日志等代码的存在会导致无法成功部署,还有环境变量的读取问题待解决。建议用 docker
Prisma文档生成器 从 Prisma 架构自动生成引用,可方便的查看 model 和 可使用的TS类型,每次运行时都会自动更新参考prisma generate。
scheme修改后,要更新文档请使用 pnpm prisma:doc
命令,html文档生成在prisma/docs
目录里。
可运行npx prisma-docs-generator serve
命令开端口查看或者手动打开html文件看。