构建一个简单的频道<->消息应用,支持TDD,E2E测试,swagger(open api)文档,CI/CD
- 源码: https://git.pincman.com/employer/forum
- API: https://forum.pincman.com/api
- Swagger:https://forum.pincman.com/api-docs
- 构建: https://drone.pincman.com 账户: employer 密码: 123456
本应用为了简单起见,使用以下技术栈
- nestjs - 一个使用typescript构建的企业级node.js框架
- typeorm - 一个node+ts构建的orm
- class-validator - 用于验证ts类
- class-transform - 用于序列化ts对象
- sqlite - 一个简单的嵌入式数据库,如果有需要你可以换成mysql或者postgresql等任意数据库
下载源码
git clone https://github.com/pincman/forum
安装pnpm
npm install -g pnpm
安装应用
cd forum && pnpm i
启动应用并热更新
pnpm start:dev
推荐使用Vscode配置开发环境
本应用的代码规范遵循airbnb标准,如果使用其它规范,譬如standard等,请自行调整
为了能身心愉悦的编辑代码,请使用以下命令安装eslint与prettier插件
code --install-extension dbaeumer.vscode-eslint \
&& code esbenp.prettier-vscode
根据自己需要的调试方式,随意调整./vscode/launch.json
文件,在任意文件打上断点,按F5
一键Debug
在Postman中导入集合(./postman/collection.json
)和(./postman/environment.json
)环境配置配置,并对接口进行测试,如下图
又或者你可以通过访问https://forum.pincman.com/api-docs来访问swagger(open api)页面进行测试
我目前使用的是gitea+drone的devops方式进行部署,步骤如下
- 先使用nginx创建一个虚拟主机反向映射到应用的端口
- 接着把代码push到应用的gitea的仓库中
- gitea通过钩子触发drone(drone.pincman.com)自动构建
- 构建进度可进入drone控制面板,使用 账户: employer,密码: 123456查看
- drone构建完毕自动把产出物(即
dist
包)通过ssh输送到生产服务器 - drone在输送完编译包后,pm2将自启对应用进行部署
drone配置请参考源代码
在drone中需要设置以下字段
- deploy_path: 生产服务器需要部署的路径
- host: 生产服务器的IP地址
- ssh_key: 构建服务器连接生成服务器用到的密匙(需要提前将公钥添加到生产服务器的
authorized_key
中) - username: 连接生产服务器的用户名
更简洁的方式
可以自行配置一个Dockerfile或者docker-compose.yml代替pm2+nginx,在drone构建后进行部署
注意事项(备注)
- 在应用比较大时中使用migration(迁移命令)来代替当前代码中的同步配置,这样在数据库结构更新后不会丢数据,迁移命令和编写方法十分简单,可参考typeorm cli文档,也可以自动利用entity生成迁移
- 尽可能使用pm2的cluster方式进行部署,这样在一个子进程挂掉的时候不会导致整个应用的崩溃
也可以使用open api(swagger)进行测试,地址: https://forum.pincman.com/api-docs,如下图
列出所有频道
API
- url: /channels
- method: GET
Response Data: 频道列表数组,每个频道的字段解释请查看频道详情
显示一个频道的详情
API
- url: /channels/:channel_id
- method: GET
Response Data
- id: 当前频道的ID
- name: 当前频道的名称
- content: 当前频道的排序
- createdAt: 当前频道下的消息数量
频道名称具有唯一性,不可重复
API
- url: /channels
- method: POST
Body
- name: 频道名称
Response Data: 请参考频道详情
频道名称重复将抛出400
异常
频道名称具有唯一性,如果已存在则抛出400
异常
API
- url: /channels
- method: PATCH
Body
- id: 频道ID
- name: 频道名称
Response Data: 请参考频道详情
频道名称重复异常
删除频道的同时会删除其下的所有消息
API
- url: /channels/:channel_id
- method: DELETE
Response Data: 请参考频道详情
按创建时间排序,支持分页,支持通过频道过滤,消息内容自动通过防xss处理,标题自动去除html标签
API
- url: /messages
- method: GET
Params
- page: 当前页
- limit: 每页显示消息数量
- channel: 只查找指定频道下的消息,通过频道ID指定
Response Data
- items: 查询出的消息列表,每个消息的字段解释请查看消息详情
- meta.totalItems: 符合条件的消息的总数量
- meta.itemCount: 当前页显示数量
- meta.itemsPerPage: 每一页显示的消息数量
- meta.totalPages: 总页数
- meta.currentPage: 当前页
如图
消息内容自动通过防xss处理,标题自动去除html标签
API
- url: /messages/:message_id
- method: GET
Response Data
- id: 当前消息的ID
- title: 当前消息的标题
- content: 当前消息的内容
- createdAt: 当前消息的创建时间
API
- url: /messages
- method: POST
Body
- title: 消息标题
- content: 消息内容
- channel: 频道ID
Response Data: 请参考消息详情
新增消息(必须通过channel
字段指定分类),对content
字段自动过滤部分html
标签以防止xss攻击,对title
清除全部html
标签,如下图
API
- url:/messages
- method:PATCH
Body
- id: 消息ID
- title: 消息标题
- content: 消息内容
- channel: 频道ID
Response Data: 请参考消息详情
更新消息可重设title
,content
以及关联的channel
,如图
API
- url: /messages/:message_id
- method:DELETE
Response Data: 请参考消息详情
src ├── app.controller.ts #框架默认文件(可废弃) ├── app.module.ts #框架默认文件(可废弃) ├── app.service.ts #框架默认文件(可废弃) ├── config │ └── database.config.ts #数据库配置文件 ├── database │ └── database.sqlite #sqlite数据库文件 ├── main.ts #应用的启动引导文件 └── modules ├── core #核心包 │ ├── constants.ts #常量文件 │ ├── constraints │ ├── core.module.ts #核心模块 │ ├── decorators #装饰器集合 │ ├── helpers.ts #一些帮助函数 │ ├── providers #自定义的全局验证管道,序列化拦截器和异常处理过滤器 │ └── types.ts #全局的类型 └── forum #社区逻辑业务包 ├── forum.module.ts #社区模块 ├── controllers #控制器 ├── dtos #请求数据验证DTO ├── entities #实体模型 ├── repositories #操作数据的自定义存储类 ├── services #服务类 └── subscribers #用于执行查询钩子的订阅者类
from https://github.com/pincman/forum
No comments:
Post a Comment