SuperAPI AI 工具集

scaffolding-nestjs-app

编程与开发

查看项目

更新于 10-22 16:19

技能介绍

概述 将空白目录(或现有 Nx 单仓内的新应用)转换为遵循作者标准基线的 NestJS 服务:pino 日志、统一 ApiResponse 契约与全局异常过滤器、ESLint/Prettier、带覆盖率的 Vitest、husky pre-commit/pre-push,以及 Docker/Compose/Makefile 部署脚手架。模板位于本文件旁的 templates/ 目录,应复制并调整,而非凭记忆重新编写。

适用场景

  • 用户要求从零创建新的 NestJS 应用/服务/微服务。
  • 用户要求向现有 Nx(或其他)单仓添加新的后端应用。
  • 不适用于向已完成脚手架的应用添加单个功能/模块——本技能仅用于初始引导。

环境检测

  • 目标仓库根目录存在 nx.json → 使用 Nx 生成器:npx nx g @nx/nest:application apps/<app-name>(如未提供应用名/路径则询问;如插件未安装,先添加 @nx/nest 至 devDependencies)。
  • 无 nx.json,但仓库已有至少一个应用/包 → 非 Nx 多应用仓库;使用 nest new <app-name> 或遵循现有结构执行 nest generate。不要静默引入 Nx。
  • 无 nx.json 且无任何现有应用(空/全新仓库)→ 必须询问用户选择 Nx 工作区(npx create-nx-workspace@latest,再使用上述生成器)还是独立 Nest CLI 应用(npx @nestjs/cli new .)。此决策影响后续模板变体(.standalone. vs 单仓版本)。

依赖安装 生产依赖:npm install nestjs-pino pino pino-http class-validator class-transformer;如需异常过滤器的 axios 错误分支则加 axios,否则跳过。 开发依赖:npm install -D pino-pretty eslint prettier eslint-config-prettier eslint-plugin-import eslint-plugin-prettier typescript-eslint vitest @vitest/coverage-v8 unplugin-swc vite-tsconfig-paths husky lint-staged。单仓中另加 @nx/eslint-plugin(如尚未存在)。安装最新版本,单仓先检查根 package.json 仅补缺失项。

生成后清理

  • 确认严格 TypeScript:独立应用检查 tsconfig.json,单仓检查 tsconfig.base.json 的 compilerOptions.strict: true,缺失则显式设置;不要关闭严格子标志来绕过类型错误。
  • 删除 Jest 脚手架:jest.config.ts/js(应用级及独立仓库根级)、test/ 目录(含 app.e2e-spec.ts、jest-e2e.json)、Jest 生成的 *.spec.ts 文件、Jest 相关 devDependencies(jest、@nestjs/testing 如非必要、ts-jest、@types/jest、jest-environment-node 等,视生成器实际添加)、package.json 内嵌 jest 配置块及指向 Jest 的 test/e2e 脚本。Nx 单仓应用还需删除 project.json 中引用 @nx/jest:jest 的 test/e2e 目标。
  • Vitest/tsc 接线:在 tsconfig.app.json 添加 "exclude": ["src//*.spec.ts", "src//*.test.ts"];创建 tsconfig.spec.json(extends ./tsconfig.json,types: ["vitest/globals"],include spec/test 文件与 vitest.config.ts);每个 spec 文件显式从 'vitest' 导入 vi。

应用基线:配置、全局前缀、验证 在 main.ts/app.module.ts 中确保:全局 ConfigModule 验证 PORT(Joi 或 class-validator,使用处 getOrThrow),app.setGlobalPrefix('api'),全局 ValidationPipe 启用 transform: true + whitelist: true + 隐式转换,以及 useContainer(app, { fallbackOnErrors: true }) 以支持 class-validator 自定义装饰器使用 Nest DI。若应用位于 Traefik 等反向代理之后,代理负责去除服务名前缀,应用自身路由保持 /api/... 不变。

应用基线:进程守卫 main.ts 必须能在请求链之外失败时存活。使用共享辅助函数(单仓中从 @chatbot-platform/helpers/nest 导入 registerProcessGuards/runBootstrap;独立应用在 src/common/process-guards/ 下创建同名函数),禁止在 main.ts 内联 process.on(...):

  • runBootstrap(bootstrap) 替代裸 bootstrap() 调用,失败时 console.error 并 exit 1。
  • registerProcessGuards({ app, logger: app.get(Logger) }) 在 app.useLogger 后调用:启用关闭钩子,在 unhandledRejection/uncaughtException 时通过 pino 记录,执行 app.close() 与超时竞速,然后 exit 1;关闭期间重复事件忽略。 如注册 @nestjs-modules/ioredis 或 BullMQ @Processor,还需附加错误监听器通过 pino 记录。

API 版本化 编写 main.ts 前询问用户是否需要 URI API 版本化,不要默认。如需,在 setGlobalPrefix 后、useContainer 前添加 VersioningType.URI 与 defaultVersion: '1',路由变为 /api/v1/...;否则路由保持 /api/...。

接入 pino 日志 复制整个 templates/pino/ 目录(五个文件:pino-config.types.ts、pino-config.constants.ts、pino-config.helpers.ts、pino-config.loader.ts、app-logger.module.ts)。单仓中多应用共享代码时放入共享库(如 libs/nest-logger),已有则直接依赖;独立应用或单仓首个应用放入 src/common/logger/。 AppLoggerOptions 控制:level、pretty(开发模式 pino-pretty 传输,生产关闭)、singleLine、pinoConfigEnabled(true 时从 cwd 加载 pino.config.json,缺失或格式错误抛错;默认 false)。环境变量 LOG_LEVEL/LOG_PRETTY/LOG_PRETTY_SINGLE_LINE/PINO_CONFIG_ENABLED 选择一种 Joi 形状并保持一致(字符串形状或布尔形状),混用会导致静默错误。字符串形状示例及 forRootAsync 接线参考原文。更新三处环境变量文件(Joi schema、根 .env.example、单仓 devops/.env.example 与 docker-compose.prod.yml)。接线后以 LOG_PRETTY=true 启动确认彩色单行输出。

异常过滤器 + 响应拦截器 先搜索现有 ExceptionFilter/响应拦截器:单仓中找到则提取至共享库并让新旧应用依赖;独立仓库中找到则复用;未找到则复制 templates/response/ 下文件,修正导入路径,若无 axios 调用则删除 axios 分支。在 app.module.ts providers 中注册(非 main.ts),ApiResponseInterceptor 放在其他 APP_INTERCEPTOR 最后。

健康端点 每个新应用获得简单无依赖存活端点,不使用 @nestjs/terminus,无 DB/Redis 就绪检查除非用户明确要求。代码示例位于原文 src/app/app.controller.ts。