{"id":14989417,"url":"https://github.com/inlym/life-helper-backend","last_synced_at":"2025-09-08T09:35:32.422Z","repository":{"id":51296257,"uuid":"274951086","full_name":"inlym/life-helper-backend","owner":"inlym","description":"「小鸣助手」项目服务端代码，使用 Nest.js 框架","archived":false,"fork":false,"pushed_at":"2021-09-08T15:46:43.000Z","size":4306,"stargazers_count":67,"open_issues_count":0,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-19T05:20:52.524Z","etag":null,"topics":["egg","eggjs","koa2","koajs","miniprogram","nest","nestjs","nodejs","serverless","weixin"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inlym.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-25T15:27:21.000Z","updated_at":"2025-01-17T16:07:02.000Z","dependencies_parsed_at":"2022-09-05T22:50:48.549Z","dependency_job_id":null,"html_url":"https://github.com/inlym/life-helper-backend","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/inlym/life-helper-backend","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inlym%2Flife-helper-backend","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inlym%2Flife-helper-backend/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inlym%2Flife-helper-backend/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inlym%2Flife-helper-backend/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inlym","download_url":"https://codeload.github.com/inlym/life-helper-backend/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inlym%2Flife-helper-backend/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274165754,"owners_count":25233952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-08T02:00:09.813Z","response_time":121,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["egg","eggjs","koa2","koajs","miniprogram","nest","nestjs","nodejs","serverless","weixin"],"created_at":"2024-09-24T14:18:19.942Z","updated_at":"2025-09-08T09:35:32.389Z","avatar_url":"https://github.com/inlym.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# life-helper-backend\r\n\r\n「我的个人助手」主要用于为用户提供一些日常使用的小工具，包含天气查询、日程管理、事项提醒等功能。\r\n\r\n## 相关仓库\r\n\r\n### 服务端\r\n\r\n仓库（当前仓库）地址： [life-helper-backend](https://github.com/inlym/life-helper-backend)\r\n\r\n技术栈： `Node.js` + `Nest.js` + `TypeScript` + `Typeorm` + `MySQL` + `Redis` + `Docker`\r\n\r\n### 小程序端\r\n\r\n仓库地址： [life-helper-miniprogram](https://github.com/inlym/life-helper-miniprogram)\r\n\r\n技术栈： `原生小程序` + `自定义的一套框架加强工具`\r\n\r\n![](https://img.inlym.com/ed5676d20f6243328c2e89a1403e4ff0.jpg)\r\n\r\n### Web 端\r\n\r\n仓库地址： [life-helper-frontend](https://github.com/inlym/life-helper-frontend)\r\n\r\n技术栈： `Angular` + `TypeScript` + `Sass` + `RxJS` + `Swagger` + `Webpack`\r\n\r\nWeb 地址： [我的个人助手](https://www.lifehelper.com.cn/)\r\n\r\n## 项目架构\r\n\r\n以下是当前项目的技术架构，可供读者参考。\r\n\r\n### 本地开发环境\r\n\r\n本地开发环境主要用于新功能开发的前期阶段，就在当前开发的电脑部署环境，`MySQL` 和 `Redis` 等服务也是自建的。\r\n\r\n### 测试环境\r\n\r\n本地开发到了较为成熟的阶段，会将代码进行提交在测试环境部署，测试环境用的是一台低配具有公网 IP 的阿里云服务器，`MySQL` 和 `Redis` 等资源购买的是阿里云的服务。\r\n\r\n### 预发布环境\r\n\r\n预发布环境处理运行代码的服务器以外，其他服务直接连生产环境的资源，用于临上线前的最后一道测试。\r\n\r\n### 生产环境\r\n\r\n#### 基本原则\r\n\r\n1. 尽量使用阿里云封装好的服务，缺点是贵，但有点是免运维，比自己部署稳定的多。例如：API 网关、负载均衡等中间件。\r\n2. 使用阿里云云效（`Codeup`）进行自动化部署，尽量避免手工上线。\r\n\r\n#### 技术架构\r\n\r\n##### 网关层\r\n\r\n1. 服务端 URL： `https://api.lifehelper.com.cn`\r\n2. 使用阿里云 [API 网关](https://www.aliyun.com/product/apigateway?userCode=lzfqdh6g) 承接 HTTP 请求，不将内部服务器直接暴露在公网上。\r\n3. 使用阿里云 [API 网关](https://www.aliyun.com/product/apigateway?userCode=lzfqdh6g) 自带的 [摘要签名认证](https://help.aliyun.com/document_detail/29475.html?userCode=lzfqdh6g) 对 HTTP 请求进行基本鉴权，保证只有我方客户端发起的 HTTP 请求才进行转发，其他非法请求全部进行拦截。\r\n4. 将合法请求转发至阿里云 [负载均衡](https://www.aliyun.com/product/slb?userCode=lzfqdh6g) 。\r\n5. [API 网关](https://www.aliyun.com/product/apigateway?userCode=lzfqdh6g) 后的所有服务，均部署在阿里云 [专有网络 VPC](https://www.aliyun.com/product/vpc?userCode=lzfqdh6g) ，与公网不互通。\r\n\r\n##### 转发层\r\n\r\n1. 合法请求由 [API 网关](https://www.aliyun.com/product/apigateway?userCode=lzfqdh6g) 转发至 [负载均衡](https://www.aliyun.com/product/slb?userCode=lzfqdh6g) 服务，再由 [负载均衡](https://www.aliyun.com/product/slb?userCode=lzfqdh6g) 转发至服务器组上。\r\n2. 服务器组按照配置情况使用 `加权轮询` 调度算法进行请求分配。\r\n\r\n##### 服务器组\r\n\r\n1. 尽量遵循 “低配多台” 的原则配置服务器，即：低配置的多台服务器的综合性能优于同价格的高配置服务器。\r\n\r\n##### Web 端\r\n\r\n1. Web 端 URL： `https://www.lifehelper.com.cn`\r\n2. 使用 `CDN` + `OSS` 的架构承接 Web 端服务。关于如何让 `OSS` 支持单页应用请看这篇文章 —— [《如何让 OSS 支持单页应用》](https://mp.weixin.qq.com/s/BW7Sh-qOz2Z1YoUlvxR-zQ)\r\n\r\n##### 使用到的阿里云服务\r\n\r\n1. [API 网关](https://www.aliyun.com/product/apigateway?userCode=lzfqdh6g)\r\n2. [负载均衡](https://www.aliyun.com/product/slb?userCode=lzfqdh6g)\r\n3. [专有网络](https://www.aliyun.com/product/vpc?userCode=lzfqdh6g)\r\n4. [云服务器](https://www.aliyun.com/product/ecs?userCode=lzfqdh6g)\r\n5. [MySQL](https://www.aliyun.com/product/rds/mysql?userCode=lzfqdh6g)\r\n6. [Redis](https://www.aliyun.com/product/kvstore?userCode=lzfqdh6g)\r\n7. [表格存储](https://www.aliyun.com/product/ots?userCode=lzfqdh6g)\r\n8. [日志服务](https://www.aliyun.com/product/sls?userCode=lzfqdh6g)\r\n9. [CDN](https://www.aliyun.com/product/cdn?userCode=lzfqdh6g)\r\n10. [对象存储](https://www.aliyun.com/product/oss?userCode=lzfqdh6g)\r\n11. [短信服务](https://www.aliyun.com/product/sms?userCode=lzfqdh6g)\r\n12. [DNS 解析](https://wanwang.aliyun.com/domain/dns?userCode=lzfqdh6g)\r\n\r\n## 最佳实践\r\n\r\n### 模块\r\n\r\n#### 根模块（root module）\r\n\r\n1. 根模块全局只有一个，路径 `src/app.module.ts`。\r\n2. 根模块负责引入特性模块和配置全局中间件。\r\n\r\n#### 特性模块（feature module）\r\n\r\n1. 按照对应功能划分模块，以模块为单位进行封装，该模块称为 “特性模块”。\r\n2. 特性模块放在 `src/modules/` 目录下，每个模块一个同名目录。\r\n3. 该功能对应的 `controller`，`service`，`model`，`interface` 等文件等放置在该特性模块内，无需再建二级目录。\r\n4. 不要在特性模块的控制器（`controller`）中直接使用共享模块的服务，而应该自建一个服务，在该服务内使用共享模块的服务，哪怕只有一行代码也要这样做。\r\n5. 每个 `*.controller.ts` 均对应一个同名 `*.dto.ts` 文件，该文件下均使用类（`class`）进行定义。\r\n6. 特性模块之间不允许相互引用，只允许引用共享模块。\r\n\r\n#### 共享模块（shared module）\r\n\r\n1. 将可能被多个特性模块用到的服务以及涉及第三方 API 的服务剥离出来，统一放置在共享模块下。\r\n2. 共享模块目录 `src/shared/`。\r\n3. 共享模块中的每个服务均需要完整测试用例。\r\n4. 共享模块仅被需要的特性模块引入，不要引入根模块。\r\n5. 共享模块内不得建立 `*.controller.ts` 和 `*.dto.ts` 文件。\r\n\r\n### 特性模块目录结构\r\n\r\n1. 以特性模块的 **业务名** 作为目录名称，一律使用 **小写** 英文字符，使用短横线（`-`）分隔，所有该业务相关文件均放置于该目录下。\r\n2. 业务模块内应至少包含一个控制器，以及和控制器同名的 DTO 文件（`*.controller.ts` 和 `*.dto.ts` 文件一一对应）。\r\n3. 比较大的子模块应新建子目录。\r\n\r\n目录示例（假设业务名为 `my-feature`）：\r\n\r\n```\r\nmy-feature/\r\n│\r\n├── my-feature.service.ts          # 主要\r\n│\r\n├── my-feature-a.controller.ts       # 控制器，每个业务模块至少对应一个控制器\r\n├── my-feature-a.dto.ts              # DTO 文件，与同名控制器一一对应\r\n│\r\n├── my-feature-b.controller.ts       # 控制器，每个业务模块至少对应一个控制器\r\n├── my-feature-b.dto.ts              # DTO 文件，与同名控制器一一对应\r\n│\r\n├── ...\r\n│\r\n├── feature-one/\r\n│   ├── feature-one.service.ts\r\n│   ├── feature-one.interface.ts\r\n│   ├── feature-one.entity.ts\r\n│   └── feature-one.model.ts\r\n│\r\n├── feature-two/\r\n│   ├── feature-two.service.ts\r\n│   ├── feature-two.interface.ts\r\n│   ├── feature-two.entity.ts\r\n│   └── feature-two.model.ts\r\n│\r\n└── ...\r\n\r\n\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finlym%2Flife-helper-backend","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finlym%2Flife-helper-backend","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finlym%2Flife-helper-backend/lists"}