@umacloud/knowledge 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/00-governance/governance-capabilities.md +557 -0
  2. package/00-governance/knowledge-map.md +39 -0
  3. package/00-governance/maintenance-policy.md +76 -0
  4. package/00-governance/review-checklist.md +81 -0
  5. package/README.md +13 -0
  6. package/ai/01-standards/agent-development-complete.md +691 -0
  7. package/ai/01-standards/llm-application-complete.md +488 -0
  8. package/ai/01-standards/mlops-complete.md +798 -0
  9. package/ai/01-standards/prompt-engineering-complete.md +646 -0
  10. package/ai/01-standards/rag-architecture-complete.md +649 -0
  11. package/ai/02-playbooks/llm-evaluation-playbook.md +847 -0
  12. package/ai/03-checklists/ai-project-checklist.md +215 -0
  13. package/ai/04-antipatterns/ai-antipatterns.md +661 -0
  14. package/ai/05-cases/case-rag-production.md +147 -0
  15. package/ai/06-glossary/ai-glossary.md +162 -0
  16. package/ai/agent-evaluation-benchmark.md +53 -0
  17. package/ai/ai-agent-memory-context-management.md +41 -0
  18. package/ai/ai-cost-capacity-optimization-playbook.md +42 -0
  19. package/ai/ai-data-security-and-compliance-playbook.md +37 -0
  20. package/ai/ai-domain-index-and-checklist.md +40 -0
  21. package/ai/ai-governance-maturity-model.md +50 -0
  22. package/ai/ai-model-selection-and-routing-strategy.md +47 -0
  23. package/ai/ai-observability-and-oncall-runbook.md +52 -0
  24. package/ai/ai-rag-engineering-playbook.md +42 -0
  25. package/ai/ai-red-team-and-safety-evaluation.md +42 -0
  26. package/ai/ai-release-readiness-and-rollback-gate.md +42 -0
  27. package/ai/llm-agent-engineering-deep-dive.md +57 -0
  28. package/ai/prompt-and-tool-guardrails.md +52 -0
  29. package/api/01-standards/enterprise-api-standards.md +198 -0
  30. package/api/01-standards/rest-api-design-guide.md +63 -0
  31. package/api/02-playbooks/api-pagination-playbook.md +93 -0
  32. package/api/02-playbooks/graphql-production-playbook.md +176 -0
  33. package/api/03-checklists/api-review-checklist.md +55 -0
  34. package/api/04-antipatterns/api-antipatterns.md +112 -0
  35. package/architecture/01-standards/api-gateway-patterns.md +496 -0
  36. package/architecture/01-standards/cloud-native-patterns.md +644 -0
  37. package/architecture/01-standards/distributed-systems-patterns.md +591 -0
  38. package/architecture/01-standards/event-driven-architecture.md +595 -0
  39. package/architecture/01-standards/microservices-patterns-complete.md +968 -0
  40. package/architecture/01-standards/microservices-patterns.md +495 -0
  41. package/architecture/01-standards/system-design-interview.md +664 -0
  42. package/architecture/02-playbooks/microservices-patterns-playbook.md +137 -0
  43. package/architecture/02-playbooks/migration-playbook.md +780 -0
  44. package/architecture/02-playbooks/system-design-playbook.md +779 -0
  45. package/architecture/03-checklists/architecture-decision-checklist.md +297 -0
  46. package/architecture/04-antipatterns/architecture-antipatterns.md +417 -0
  47. package/architecture/05-cases/case-netflix-microservices.md +413 -0
  48. package/architecture/06-glossary/architecture-glossary.md +164 -0
  49. package/architecture/adr-template-and-examples.md +38 -0
  50. package/architecture/api-gateway-deep-dive.md +1291 -0
  51. package/architecture/configuration-management.md +1162 -0
  52. package/architecture/distributed-transactions.md +1220 -0
  53. package/architecture/microservices-complete.md +735 -0
  54. package/architecture/resilience-and-disaster-patterns.md +37 -0
  55. package/architecture/service-governance.md +1198 -0
  56. package/architecture/system-architecture-deep-dive.md +37 -0
  57. package/backend/01-standards/analytics-and-growth.md +65 -0
  58. package/backend/01-standards/api-and-error-conventions.md +120 -0
  59. package/backend/01-standards/application-layering-and-packaging.md +160 -0
  60. package/backend/01-standards/auth-implementation.md +104 -0
  61. package/backend/01-standards/backend-framework-idioms.md +74 -0
  62. package/backend/01-standards/background-jobs-and-async.md +66 -0
  63. package/backend/01-standards/caching-strategies-complete.md +390 -0
  64. package/backend/01-standards/config-and-observability.md +77 -0
  65. package/backend/01-standards/data-modeling-and-persistence.md +94 -0
  66. package/backend/01-standards/django-complete.md +1765 -0
  67. package/backend/01-standards/email-and-notifications.md +64 -0
  68. package/backend/01-standards/fastapi-complete.md +925 -0
  69. package/backend/01-standards/file-upload-and-storage.md +66 -0
  70. package/backend/01-standards/graphql-api-complete.md +416 -0
  71. package/backend/01-standards/llm-application-standard.md +78 -0
  72. package/backend/01-standards/message-queue-patterns.md +379 -0
  73. package/backend/01-standards/microservices-and-distributed.md +78 -0
  74. package/backend/01-standards/nestjs-complete.md +2167 -0
  75. package/backend/01-standards/payment-integration.md +80 -0
  76. package/backend/01-standards/rate-limiting-complete.md +451 -0
  77. package/backend/01-standards/realtime-and-websocket.md +65 -0
  78. package/backend/01-standards/search-and-filtering.md +64 -0
  79. package/backend/01-standards/spring-boot-complete.md +445 -0
  80. package/backend/02-playbooks/api-design-playbook.md +718 -0
  81. package/backend/02-playbooks/email-send-playbook.md +130 -0
  82. package/backend/02-playbooks/file-upload-s3-playbook.md +153 -0
  83. package/backend/02-playbooks/typescript-enterprise-playbook.md +133 -0
  84. package/backend/02-playbooks/websocket-realtime-playbook.md +154 -0
  85. package/backend/03-checklists/api-launch-checklist.md +189 -0
  86. package/backend/04-antipatterns/backend-antipatterns.md +1051 -0
  87. package/blockchain/01-standards/blockchain-basics.md +557 -0
  88. package/blockchain/01-standards/smart-contract-development.md +1315 -0
  89. package/cicd/01-standards/deployment-and-delivery-standard.md +96 -0
  90. package/cicd/01-standards/github-actions-complete.md +473 -0
  91. package/cicd/01-standards/release-and-store-submission.md +75 -0
  92. package/cicd/02-playbooks/cicd-pipeline-playbook.md +144 -0
  93. package/cicd/02-playbooks/release-management-playbook.md +605 -0
  94. package/cicd/03-checklists/pipeline-security-checklist.md +168 -0
  95. package/cicd/04-antipatterns/cicd-antipatterns.md +589 -0
  96. package/cicd/05-cases/case-deployment-automation.md +221 -0
  97. package/cicd/05-cases/case-gitops-transformation.md +212 -0
  98. package/cicd/06-glossary/cicd-glossary.md +114 -0
  99. package/cicd/cicd-blueprint-deep-dive.md +38 -0
  100. package/cicd/release-readiness-gate.md +37 -0
  101. package/cloud-native/01-standards/container-security.md +741 -0
  102. package/cloud-native/01-standards/kubernetes-complete.md +812 -0
  103. package/cloud-native/02-playbooks/api-gateway-playbook.md +155 -0
  104. package/cloud-native/02-playbooks/gitops-with-argocd.md +760 -0
  105. package/cloud-native/02-playbooks/k8s-troubleshooting-playbook.md +1942 -0
  106. package/cloud-native/02-playbooks/message-queue-playbook.md +129 -0
  107. package/cloud-native/02-playbooks/multicloud-governance.md +726 -0
  108. package/cloud-native/02-playbooks/serverless-patterns.md +788 -0
  109. package/cloud-native/02-playbooks/service-mesh-playbook.md +612 -0
  110. package/cloud-native/02-playbooks/terraform-iac-playbook.md +143 -0
  111. package/cloud-native/03-checklists/container-security-checklist.md +431 -0
  112. package/cloud-native/03-checklists/k8s-production-readiness-checklist.md +460 -0
  113. package/cloud-native/04-antipatterns/container-antipatterns.md +660 -0
  114. package/cloud-native/04-antipatterns/k8s-antipatterns.md +743 -0
  115. package/cloud-native/05-cases/case-k8s-migration.md +478 -0
  116. package/cloud-native/05-cases/case-k8s-scaling.md +642 -0
  117. package/cloud-native/05-cases/case-k8s-security-incident.md +397 -0
  118. package/cloud-native/06-glossary/cloud-native-glossary.md +337 -0
  119. package/cross-platform/01-standards/cross-platform-frameworks.md +83 -0
  120. package/cross-platform/01-standards/platform-selection-and-architecture.md +77 -0
  121. package/data/01-standards/elasticsearch-complete.md +2098 -0
  122. package/data/01-standards/postgresql-complete.md +1613 -0
  123. package/data/01-standards/redis-complete.md +1527 -0
  124. package/data/02-playbooks/database-optimization-playbook.md +403 -0
  125. package/data/02-playbooks/elasticsearch-production-playbook.md +132 -0
  126. package/data/03-checklists/database-launch-checklist.md +187 -0
  127. package/data/04-antipatterns/database-antipatterns.md +873 -0
  128. package/data/05-cases/case-database-migration.md +310 -0
  129. package/data/06-glossary/database-glossary.md +440 -0
  130. package/data/data-governance-and-modeling-deep-dive.md +39 -0
  131. package/data-engineering/01-standards/airflow-complete.md +523 -0
  132. package/data-engineering/01-standards/kafka-complete.md +1521 -0
  133. package/data-engineering/02-playbooks/spark-etl-playbook.md +496 -0
  134. package/data-engineering/03-checklists/pipeline-launch-checklist.md +194 -0
  135. package/data-engineering/04-antipatterns/data-pipeline-antipatterns.md +684 -0
  136. package/data-engineering/05-cases/case-real-time-pipeline.md +355 -0
  137. package/data-engineering/06-glossary/data-engineering-glossary.md +429 -0
  138. package/database/01-standards/database-schema-standards.md +147 -0
  139. package/database/02-playbooks/postgresql-optimization-quick.md +52 -0
  140. package/database/02-playbooks/postgresql-performance-optimization.md +58 -0
  141. package/database/02-playbooks/postgresql-production-playbook.md +146 -0
  142. package/database/02-playbooks/redis-caching-playbook.md +117 -0
  143. package/database/03-checklists/database-review-checklist.md +50 -0
  144. package/database/04-antipatterns/database-antipatterns.md +112 -0
  145. package/design/01-standards/ui-design-system-complete.md +423 -0
  146. package/design/02-playbooks/design-handoff-playbook.md +254 -0
  147. package/design/02-playbooks/design-review-playbook.md +388 -0
  148. package/design/03-checklists/design-review-checklist.md +246 -0
  149. package/design/04-antipatterns/design-antipatterns.md +378 -0
  150. package/design/05-cases/case-design-system-adoption.md +328 -0
  151. package/design/06-glossary/design-glossary.md +329 -0
  152. package/design/ui-full-lifecycle-cross-platform-playbook.md +571 -0
  153. package/design/ux-system-deep-dive.md +38 -0
  154. package/design-systems/00-craft-rules.md +71 -0
  155. package/design-systems/aesthetic-families.md +43 -0
  156. package/design-systems/anti-ai-slop.md +162 -0
  157. package/design-systems/bold-geometric.md +120 -0
  158. package/design-systems/brutalist-bold.md +103 -0
  159. package/design-systems/editorial-clean.md +109 -0
  160. package/design-systems/glass-aurora.md +108 -0
  161. package/design-systems/modern-minimal.md +145 -0
  162. package/design-systems/premium-luxury.md +106 -0
  163. package/design-systems/product-type-design-map.md +48 -0
  164. package/design-systems/soft-warm.md +123 -0
  165. package/design-systems/tech-utility.md +113 -0
  166. package/desktop/01-standards/desktop-app-standard.md +72 -0
  167. package/desktop/01-standards/desktop-design.md +71 -0
  168. package/development/00-governance/document-template.md +41 -0
  169. package/development/01-standards/api-versioning-strategies.md +432 -0
  170. package/development/01-standards/authentication-patterns-complete.md +479 -0
  171. package/development/01-standards/css-architecture-complete.md +550 -0
  172. package/development/01-standards/database-migration-strategies.md +484 -0
  173. package/development/01-standards/elasticsearch-complete.md +347 -0
  174. package/development/01-standards/git-complete.md +371 -0
  175. package/development/01-standards/golang-complete.md +1565 -0
  176. package/development/01-standards/graphql-complete.md +298 -0
  177. package/development/01-standards/javascript-bundlers-complete.md +469 -0
  178. package/development/01-standards/javascript-typescript-complete.md +528 -0
  179. package/development/01-standards/jest-complete.md +275 -0
  180. package/development/01-standards/linux-complete.md +234 -0
  181. package/development/01-standards/logging-observability-complete.md +526 -0
  182. package/development/01-standards/microservices-communication.md +502 -0
  183. package/development/01-standards/mongodb-complete.md +406 -0
  184. package/development/01-standards/oauth2-complete.md +285 -0
  185. package/development/01-standards/performance-optimization-complete.md +289 -0
  186. package/development/01-standards/playwright-complete.md +247 -0
  187. package/development/01-standards/postgresql-complete.md +456 -0
  188. package/development/01-standards/pytest-complete.md +340 -0
  189. package/development/01-standards/python-async-programming.md +902 -0
  190. package/development/01-standards/python-complete.md +956 -0
  191. package/development/01-standards/python-decorators-complete.md +799 -0
  192. package/development/01-standards/python-design-patterns.md +2854 -0
  193. package/development/01-standards/python-packaging-distribution.md +420 -0
  194. package/development/01-standards/python-testing-strategies.md +607 -0
  195. package/development/01-standards/python-web-frameworks-comparison.md +471 -0
  196. package/development/01-standards/redis-complete.md +317 -0
  197. package/development/01-standards/rest-api-complete.md +316 -0
  198. package/development/01-standards/rust-complete.md +578 -0
  199. package/development/01-standards/typescript-advanced-types.md +1513 -0
  200. package/development/01-standards/web-security-complete.md +292 -0
  201. package/development/02-playbooks/api-design-playbook.md +810 -0
  202. package/development/02-playbooks/database-migration-playbook.md +580 -0
  203. package/development/02-playbooks/debugging-playbook.md +692 -0
  204. package/development/02-playbooks/feature-delivery-playbook.md +430 -0
  205. package/development/02-playbooks/incident-hotfix-playbook.md +387 -0
  206. package/development/02-playbooks/performance-optimization-playbook.md +531 -0
  207. package/development/02-playbooks/performance-tuning-playbook.md +652 -0
  208. package/development/02-playbooks/refactor-playbook.md +403 -0
  209. package/development/02-playbooks/release-playbook.md +469 -0
  210. package/development/03-checklists/architecture-review-checklist.md +168 -0
  211. package/development/03-checklists/data-migration-checklist.md +157 -0
  212. package/development/03-checklists/oncall-handover-checklist.md +173 -0
  213. package/development/03-checklists/pr-checklist.md +158 -0
  214. package/development/03-checklists/production-readiness-checklist.md +190 -0
  215. package/development/03-checklists/release-readiness-checklist.md +154 -0
  216. package/development/03-checklists/security-review-checklist.md +182 -0
  217. package/development/04-antipatterns/api-antipatterns.md +657 -0
  218. package/development/04-antipatterns/architecture-antipatterns.md +686 -0
  219. package/development/04-antipatterns/backend-antipatterns.md +648 -0
  220. package/development/04-antipatterns/cicd-antipatterns.md +540 -0
  221. package/development/04-antipatterns/code-smell-antipatterns.md +571 -0
  222. package/development/04-antipatterns/data-antipatterns.md +658 -0
  223. package/development/04-antipatterns/database-antipatterns.md +578 -0
  224. package/development/04-antipatterns/frontend-antipatterns.md +635 -0
  225. package/development/04-antipatterns/reliability-antipatterns.md +700 -0
  226. package/development/04-antipatterns/security-antipatterns.md +747 -0
  227. package/development/05-cases/case-api-version-migration.md +428 -0
  228. package/development/05-cases/case-authorization-hardening.md +383 -0
  229. package/development/05-cases/case-bluegreen-rollback.md +466 -0
  230. package/development/05-cases/case-cache-snowball-protection.md +485 -0
  231. package/development/05-cases/case-ci-cd-pipeline.md +544 -0
  232. package/development/05-cases/case-database-scaling.md +500 -0
  233. package/development/05-cases/case-db-hotspot-optimization.md +487 -0
  234. package/development/05-cases/case-incident-mttr-reduction.md +563 -0
  235. package/development/05-cases/case-microservice-migration.md +375 -0
  236. package/development/05-cases/case-performance-optimization.md +406 -0
  237. package/development/05-cases/case-security-incident-response.md +345 -0
  238. package/development/06-glossary/full-stack-glossary.md +166 -0
  239. package/development/09-maturity/quarterly-audit-template.md +35 -0
  240. package/development/11-ui-excellence/ui-aesthetic-system.md +41 -0
  241. package/development/11-ui-excellence/ui-engineering-excellence.md +435 -0
  242. package/development/12-scenarios/development-scenarios-guide.md +565 -0
  243. package/development/13-implementation-assets/implementation-toolkit.md +282 -0
  244. package/development/13-implementation-assets/knowledge-gates-execution.md +43 -0
  245. package/development/14-full-lifecycle/software-lifecycle-gates.md +511 -0
  246. package/development/15-lifecycle-templates/project-templates-collection.md +791 -0
  247. package/development/api-contract-and-versioning-guide.md +36 -0
  248. package/development/api-governance-complete.md +43 -0
  249. package/development/backend-engineering-complete.md +43 -0
  250. package/development/code-review-quality-complete.md +43 -0
  251. package/development/concurrency-reliability-complete.md +43 -0
  252. package/development/database-engineering-complete.md +43 -0
  253. package/development/engineering-effectiveness-complete.md +43 -0
  254. package/development/engineering-standards-deep-dive.md +38 -0
  255. package/development/frontend-engineering-complete.md +43 -0
  256. package/development/performance-capacity-complete.md +43 -0
  257. package/development/refactor-migration-complete.md +42 -0
  258. package/development/refactoring-and-techdebt-playbook.md +37 -0
  259. package/development/security-in-development-complete.md +43 -0
  260. package/devops/01-standards/cicd-pipeline-complete.md +262 -0
  261. package/devops/01-standards/docker-complete.md +1490 -0
  262. package/devops/01-standards/github-actions-complete.md +337 -0
  263. package/devops/01-standards/kubernetes-complete.md +638 -0
  264. package/devops/01-standards/terraform-complete.md +2117 -0
  265. package/devops/02-playbooks/docker-compose-playbook.md +233 -0
  266. package/devops/02-playbooks/docker-k8s-production-playbook.md +186 -0
  267. package/devops/02-playbooks/docker-production-playbook.md +952 -0
  268. package/edge-iot/01-standards/edge-iot-complete.md +473 -0
  269. package/experts/architect/api-design.md +178 -0
  270. package/experts/architect/methodology.md +124 -0
  271. package/experts/architect/security.md +75 -0
  272. package/experts/backend-lead/methodology.md +216 -0
  273. package/experts/devops/methodology.md +160 -0
  274. package/experts/frontend-lead/methodology.md +178 -0
  275. package/experts/product-manager/industry/ecommerce.md +43 -0
  276. package/experts/product-manager/industry/saas.md +40 -0
  277. package/experts/product-manager/methodology.md +97 -0
  278. package/experts/qa-lead/methodology.md +123 -0
  279. package/experts/qa-lead/test-strategy.md +128 -0
  280. package/experts/uiux-designer/methodology.md +125 -0
  281. package/frontend/01-standards/accessibility-complete.md +532 -0
  282. package/frontend/01-standards/accessibility-standard.md +74 -0
  283. package/frontend/01-standards/admin-dashboard-and-crud.md +72 -0
  284. package/frontend/01-standards/design-tokens-complete.md +444 -0
  285. package/frontend/01-standards/forms-and-validation.md +77 -0
  286. package/frontend/01-standards/frontend-architecture-and-layering.md +119 -0
  287. package/frontend/01-standards/i18n-and-localization.md +65 -0
  288. package/frontend/01-standards/nextjs-complete.md +451 -0
  289. package/frontend/01-standards/react-complete.md +713 -0
  290. package/frontend/01-standards/react-hooks-complete-guide.md +1100 -0
  291. package/frontend/01-standards/react-hooks-complete.md +1171 -0
  292. package/frontend/01-standards/seo-and-web-vitals.md +77 -0
  293. package/frontend/01-standards/state-management-complete.md +444 -0
  294. package/frontend/01-standards/vue-complete.md +499 -0
  295. package/frontend/01-standards/vue3-complete.md +2002 -0
  296. package/frontend/01-standards/web-framework-best-practices.md +64 -0
  297. package/frontend/01-standards/web-performance-complete.md +495 -0
  298. package/frontend/02-playbooks/accessibility-a11y-playbook.md +161 -0
  299. package/frontend/02-playbooks/frontend-performance-playbook.md +707 -0
  300. package/frontend/02-playbooks/i18n-internationalization-playbook.md +120 -0
  301. package/frontend/02-playbooks/performance-optimization-playbook.md +163 -0
  302. package/frontend/02-playbooks/react-nextjs-production-playbook.md +167 -0
  303. package/frontend/02-playbooks/react-state-management-playbook.md +173 -0
  304. package/frontend/03-checklists/component-quality-checklist.md +166 -0
  305. package/frontend/03-checklists/frontend-launch-checklist.md +299 -0
  306. package/frontend/04-antipatterns/frontend-antipatterns.md +886 -0
  307. package/frontend/05-cases/case-performance-optimization.md +274 -0
  308. package/harmony/01-standards/harmonyos-arkts-standard.md +75 -0
  309. package/harmony/01-standards/harmonyos-design.md +65 -0
  310. package/high-quality-engineering-playbook.md +54 -0
  311. package/incident/01-standards/incident-response-complete.md +303 -0
  312. package/incident/02-playbooks/chaos-engineering-playbook.md +883 -0
  313. package/incident/02-playbooks/postmortem-playbook.md +398 -0
  314. package/incident/03-checklists/incident-readiness-checklist.md +181 -0
  315. package/incident/04-antipatterns/incident-antipatterns.md +490 -0
  316. package/incident/05-cases/case-cascade-failure.md +176 -0
  317. package/incident/06-glossary/incident-glossary.md +114 -0
  318. package/incident/postmortem-and-response-deep-dive.md +39 -0
  319. package/industries/ecommerce/ecommerce-complete.md +631 -0
  320. package/industries/education/education-complete.md +555 -0
  321. package/industries/fintech/fintech-complete.md +501 -0
  322. package/industries/gaming/gaming-complete.md +587 -0
  323. package/industries/healthcare/healthcare-complete.md +452 -0
  324. package/low-code/01-standards/low-code-complete.md +944 -0
  325. package/miniprogram/01-standards/ai-common-mistakes.md +61 -0
  326. package/miniprogram/01-standards/miniprogram-custom-navbar-capsule.md +77 -0
  327. package/miniprogram/01-standards/miniprogram-design.md +61 -0
  328. package/miniprogram/01-standards/miniprogram-standard.md +81 -0
  329. package/mobile/01-standards/android-material-design.md +70 -0
  330. package/mobile/01-standards/flutter-complete.md +384 -0
  331. package/mobile/01-standards/ios-design-hig.md +78 -0
  332. package/mobile/01-standards/mobile-app-standard.md +85 -0
  333. package/mobile/01-standards/react-native-complete.md +352 -0
  334. package/mobile/02-playbooks/mobile-cross-platform-playbook.md +175 -0
  335. package/mobile/02-playbooks/mobile-performance.md +473 -0
  336. package/mobile/03-checklists/mobile-release-checklist.md +234 -0
  337. package/mobile/04-antipatterns/mobile-antipatterns.md +798 -0
  338. package/mobile/05-cases/case-app-performance.md +500 -0
  339. package/mobile/05-cases/case-app-startup-optimization.md +218 -0
  340. package/mobile/06-glossary/mobile-glossary.md +484 -0
  341. package/observability/01-standards/observability-standards.md +103 -0
  342. package/observability/02-playbooks/prometheus-grafana-playbook.md +135 -0
  343. package/observability/02-playbooks/structured-logging-playbook.md +73 -0
  344. package/observability/03-checklists/observability-checklist.md +54 -0
  345. package/observability/04-antipatterns/observability-antipatterns.md +106 -0
  346. package/operations/01-standards/prometheus-monitoring-complete.md +1578 -0
  347. package/operations/02-playbooks/capacity-planning-playbook.md +620 -0
  348. package/operations/03-checklists/production-launch-checklist.md +365 -0
  349. package/operations/04-antipatterns/operations-antipatterns.md +664 -0
  350. package/operations/05-cases/case-sre-practices.md +581 -0
  351. package/operations/06-glossary/operations-glossary.md +120 -0
  352. package/operations/aiops-anomaly-detection.md +758 -0
  353. package/operations/capacity-planning.md +1061 -0
  354. package/operations/chaos-engineering.md +659 -0
  355. package/operations/incident-command-system.md +38 -0
  356. package/operations/observability-complete.md +442 -0
  357. package/operations/slo-sli-playbook.md +517 -0
  358. package/operations/sre-operations-deep-dive.md +39 -0
  359. package/package.json +8 -0
  360. package/performance/01-standards/performance-and-scalability.md +80 -0
  361. package/performance/01-standards/performance-standards.md +156 -0
  362. package/performance/02-playbooks/query-optimization-playbook.md +103 -0
  363. package/performance/03-checklists/performance-checklist.md +56 -0
  364. package/performance/04-antipatterns/performance-antipatterns.md +146 -0
  365. package/product/01-standards/product-management-complete.md +285 -0
  366. package/product/02-playbooks/feature-launch-playbook.md +207 -0
  367. package/product/02-playbooks/user-research-playbook.md +532 -0
  368. package/product/03-checklists/feature-launch-checklist.md +275 -0
  369. package/product/04-antipatterns/product-antipatterns.md +355 -0
  370. package/product/05-cases/case-mvp-to-scale.md +384 -0
  371. package/product/06-glossary/product-glossary.md +462 -0
  372. package/product/feature-prioritization-framework.md +40 -0
  373. package/product/kpi-and-metric-tree.md +37 -0
  374. package/product/product-discovery-and-prd-deep-dive.md +41 -0
  375. package/quantum/01-standards/quantum-complete.md +1186 -0
  376. package/security/01-standards/api-security-complete.md +511 -0
  377. package/security/01-standards/container-runtime-security.md +574 -0
  378. package/security/01-standards/data-protection-gdpr.md +543 -0
  379. package/security/01-standards/owasp-top10-complete.md +1890 -0
  380. package/security/01-standards/secure-coding-baseline.md +90 -0
  381. package/security/01-standards/supply-chain-security.md +441 -0
  382. package/security/01-standards/web-security-checklist.md +108 -0
  383. package/security/01-standards/zero-trust-architecture.md +521 -0
  384. package/security/02-playbooks/auth-sso-playbook.md +166 -0
  385. package/security/02-playbooks/incident-response-security-playbook.md +588 -0
  386. package/security/02-playbooks/owasp-api-security-playbook.md +129 -0
  387. package/security/02-playbooks/payment-integration-playbook.md +119 -0
  388. package/security/02-playbooks/penetration-testing-playbook.md +517 -0
  389. package/security/03-checklists/security-audit-checklist.md +356 -0
  390. package/security/04-antipatterns/security-coding-antipatterns.md +580 -0
  391. package/security/05-cases/case-log4shell-incident.md +537 -0
  392. package/security/05-cases/case-major-breaches.md +468 -0
  393. package/security/06-glossary/security-glossary.md +212 -0
  394. package/security/compliance-automation.md +993 -0
  395. package/security/container-security.md +680 -0
  396. package/security/devsecops-complete.md +426 -0
  397. package/security/sast-dast-sca.md +775 -0
  398. package/security/secrets-management.md +594 -0
  399. package/security/security-architecture-deep-dive.md +37 -0
  400. package/security/threat-modeling-stride-playbook.md +40 -0
  401. package/seed-templates/auth-system.md +59 -0
  402. package/seed-templates/blog-content.md +94 -0
  403. package/seed-templates/dashboard.md +89 -0
  404. package/seed-templates/docs-site.md +73 -0
  405. package/seed-templates/e-commerce.md +50 -0
  406. package/seed-templates/saas-landing.md +92 -0
  407. package/seed-templates/settings-page.md +51 -0
  408. package/testing/01-standards/test-strategy-and-layering.md +83 -0
  409. package/testing/01-standards/testing-strategy-complete.md +422 -0
  410. package/testing/01-standards/unit-testing-best-practices.md +118 -0
  411. package/testing/02-playbooks/e2e-testing-playbook.md +988 -0
  412. package/testing/02-playbooks/testing-strategy-playbook.md +126 -0
  413. package/testing/03-checklists/test-strategy-checklist.md +208 -0
  414. package/testing/04-antipatterns/testing-antipatterns.md +718 -0
  415. package/testing/05-cases/case-testing-transformation.md +300 -0
  416. package/testing/06-glossary/testing-glossary.md +110 -0
  417. package/testing/risk-based-test-matrix.md +36 -0
  418. package/testing/testing-strategy-deep-dive.md +37 -0
@@ -0,0 +1,2167 @@
1
+ ---
2
+ id: nestjs-complete
3
+ title: NestJS 完整指南
4
+ domain: backend
5
+ category: 01-standards
6
+ difficulty: intermediate
7
+ tags: [backend, complete, nestjs, websocket, 依赖注入系统, 微服务, 快速开始, 数据库集成]
8
+ quality_score: 70
9
+ last_updated: 2026-06-15
10
+ ---
11
+ # NestJS 完整指南
12
+
13
+ ## 概述
14
+
15
+ NestJS 是一个用于构建高效、可扩展 Node.js 服务端应用的渐进式框架。它完全使用 TypeScript 构建(同时兼容纯 JavaScript),融合了面向对象编程 (OOP)、函数式编程 (FP) 和函数式响应式编程 (FRP) 的理念。底层默认使用 Express,但也支持切换到 Fastify 以获得更高性能。
16
+
17
+ ### NestJS vs Express vs Fastify
18
+
19
+ | 特性 | NestJS | Express | Fastify |
20
+ |------|--------|---------|---------|
21
+ | 架构模式 | 模块化 + 依赖注入 | 无约定,极简 | 插件体系 |
22
+ | TypeScript 支持 | 原生一等公民 | 需手动配置 | 内置支持 |
23
+ | 性能(req/s 基准) | 与底层适配器一致 | ~15k | ~30k |
24
+ | 学习曲线 | 中高(Angular 风格) | 低 | 低-中 |
25
+ | 依赖注入 | 内置 IoC 容器 | 无 | 无 |
26
+ | 微服务支持 | 内置多种 Transport | 无(需第三方) | 无(需第三方) |
27
+ | WebSocket | 内置 Gateway | 需 socket.io | 需插件 |
28
+ | GraphQL | 官方模块 | 需 Apollo 手动集成 | 需 Mercurius |
29
+ | 测试工具 | Testing 模块 + 自动 Mock | 需自行搭建 | 需自行搭建 |
30
+ | 企业级就绪度 | 高 | 中 | 中 |
31
+
32
+ ### 何时选择 NestJS
33
+
34
+ ✅ **大型团队协作**: 强约定 + 模块化架构减少代码风格分歧
35
+ ✅ **微服务体系**: 内置 Transport 层,支持 Redis/Kafka/gRPC/NATS/MQTT
36
+ ✅ **企业级后端**: 完善的认证/授权/缓存/队列/日志/健康检查生态
37
+ ✅ **全栈 TypeScript**: 前后端共享类型定义,配合 Monorepo 高效开发
38
+ ✅ **需要长期维护的系统**: 模块边界清晰,重构成本低
39
+
40
+ ❌ **简单 API / 原型验证**: 过度工程化,Express/Fastify 更轻便
41
+ ❌ **极致性能场景**: 框架层带来一定开销,考虑 Fastify 或 Go
42
+
43
+ ---
44
+
45
+ ## 快速开始
46
+
47
+ ### 安装
48
+
49
+ ```bash
50
+ # 使用 CLI 创建项目(推荐)
51
+ npm i -g @nestjs/cli
52
+ nest new my-project
53
+
54
+ # 手动安装核心包
55
+ npm i @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata rxjs
56
+ ```
57
+
58
+ ### Hello World
59
+
60
+ ```typescript
61
+ // main.ts
62
+ import { NestFactory } from '@nestjs/core';
63
+ import { AppModule } from './app.module';
64
+
65
+ async function bootstrap() {
66
+ const app = await NestFactory.create(AppModule);
67
+ await app.listen(3000);
68
+ }
69
+ bootstrap();
70
+
71
+ // app.module.ts
72
+ import { Module } from '@nestjs/common';
73
+ import { AppController } from './app.controller';
74
+ import { AppService } from './app.service';
75
+
76
+ @Module({
77
+ imports: [],
78
+ controllers: [AppController],
79
+ providers: [AppService],
80
+ })
81
+ export class AppModule {}
82
+
83
+ // app.controller.ts
84
+ import { Controller, Get } from '@nestjs/common';
85
+ import { AppService } from './app.service';
86
+
87
+ @Controller()
88
+ export class AppController {
89
+ constructor(private readonly appService: AppService) {}
90
+
91
+ @Get()
92
+ getHello(): string {
93
+ return this.appService.getHello();
94
+ }
95
+ }
96
+
97
+ // app.service.ts
98
+ import { Injectable } from '@nestjs/common';
99
+
100
+ @Injectable()
101
+ export class AppService {
102
+ getHello(): string {
103
+ return 'Hello World!';
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### CLI 常用命令
109
+
110
+ ```bash
111
+ nest generate module users # 生成模块
112
+ nest generate controller users # 生成控制器
113
+ nest generate service users # 生成服务
114
+ nest generate resource users # 一键生成完整 CRUD 资源(模块+控制器+服务+DTO+实体)
115
+ nest build # 编译项目
116
+ nest start --watch # 开发模式热重载
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 核心概念
122
+
123
+ ### 1. 模块 (Modules)
124
+
125
+ 模块是 NestJS 应用的基本组织单元。每个应用至少有一个根模块 (AppModule)。
126
+
127
+ ```typescript
128
+ import { Module, Global } from '@nestjs/common';
129
+ import { UsersController } from './users.controller';
130
+ import { UsersService } from './users.service';
131
+ import { AuthModule } from '../auth/auth.module';
132
+
133
+ @Module({
134
+ imports: [AuthModule], // 导入其他模块
135
+ controllers: [UsersController], // 注册控制器
136
+ providers: [UsersService], // 注册提供者
137
+ exports: [UsersService], // 导出供其他模块使用
138
+ })
139
+ export class UsersModule {}
140
+
141
+ // 全局模块 — 导入一次,全局可用
142
+ @Global()
143
+ @Module({
144
+ providers: [ConfigService],
145
+ exports: [ConfigService],
146
+ })
147
+ export class ConfigModule {}
148
+
149
+ // 动态模块 — 根据参数动态配置
150
+ @Module({})
151
+ export class DatabaseModule {
152
+ static forRoot(options: DatabaseOptions): DynamicModule {
153
+ return {
154
+ module: DatabaseModule,
155
+ providers: [
156
+ {
157
+ provide: 'DATABASE_OPTIONS',
158
+ useValue: options,
159
+ },
160
+ DatabaseService,
161
+ ],
162
+ exports: [DatabaseService],
163
+ global: true,
164
+ };
165
+ }
166
+
167
+ static forFeature(entities: Type[]): DynamicModule {
168
+ const providers = entities.map((entity) => ({
169
+ provide: getRepositoryToken(entity),
170
+ useFactory: (ds: DataSource) => ds.getRepository(entity),
171
+ inject: [DataSource],
172
+ }));
173
+ return {
174
+ module: DatabaseModule,
175
+ providers,
176
+ exports: providers,
177
+ };
178
+ }
179
+ }
180
+ ```
181
+
182
+ ### 2. 控制器 (Controllers)
183
+
184
+ 控制器负责处理传入请求并返回响应。
185
+
186
+ ```typescript
187
+ import {
188
+ Controller, Get, Post, Put, Delete, Patch,
189
+ Param, Query, Body, Headers, Ip,
190
+ HttpCode, HttpStatus, Redirect, Header,
191
+ Res, Req, ParseIntPipe, ParseUUIDPipe,
192
+ UseGuards, UseInterceptors, UsePipes,
193
+ } from '@nestjs/common';
194
+ import { Request, Response } from 'express';
195
+
196
+ @Controller('users') // 路由前缀 /users
197
+ export class UsersController {
198
+ constructor(private readonly usersService: UsersService) {}
199
+
200
+ @Get()
201
+ findAll(@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number) {
202
+ return this.usersService.findAll(page);
203
+ }
204
+
205
+ @Get(':id')
206
+ findOne(@Param('id', ParseUUIDPipe) id: string) {
207
+ return this.usersService.findOne(id);
208
+ }
209
+
210
+ @Post()
211
+ @HttpCode(HttpStatus.CREATED)
212
+ create(@Body() createUserDto: CreateUserDto) {
213
+ return this.usersService.create(createUserDto);
214
+ }
215
+
216
+ @Put(':id')
217
+ update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
218
+ return this.usersService.update(id, updateUserDto);
219
+ }
220
+
221
+ @Delete(':id')
222
+ @HttpCode(HttpStatus.NO_CONTENT)
223
+ remove(@Param('id') id: string) {
224
+ return this.usersService.remove(id);
225
+ }
226
+
227
+ // 子路由分组
228
+ @Get(':id/orders')
229
+ findUserOrders(@Param('id') id: string) {
230
+ return this.usersService.findOrders(id);
231
+ }
232
+
233
+ // 自定义响应(绕过序列化)
234
+ @Get(':id/avatar')
235
+ async getAvatar(@Param('id') id: string, @Res() res: Response) {
236
+ const stream = await this.usersService.getAvatar(id);
237
+ stream.pipe(res);
238
+ }
239
+ }
240
+
241
+ // 版本控制
242
+ @Controller({ path: 'users', version: '2' })
243
+ export class UsersV2Controller {
244
+ // /v2/users
245
+ }
246
+ ```
247
+
248
+ ### 3. 提供者 (Providers)
249
+
250
+ 提供者是 NestJS 依赖注入的核心。任何被 `@Injectable()` 修饰的类都可作为提供者。
251
+
252
+ ```typescript
253
+ import { Injectable, Scope, Inject } from '@nestjs/common';
254
+
255
+ @Injectable()
256
+ export class UsersService {
257
+ constructor(
258
+ @Inject('USER_REPOSITORY') private userRepo: Repository<User>,
259
+ private readonly configService: ConfigService,
260
+ ) {}
261
+
262
+ async findAll(page: number): Promise<PaginatedResult<User>> {
263
+ const take = this.configService.get<number>('PAGE_SIZE', 20);
264
+ const skip = (page - 1) * take;
265
+ const [data, total] = await this.userRepo.findAndCount({ take, skip });
266
+ return { data, total, page, pageSize: take };
267
+ }
268
+
269
+ async findOne(id: string): Promise<User> {
270
+ const user = await this.userRepo.findOne({ where: { id } });
271
+ if (!user) {
272
+ throw new NotFoundException(`User #${id} not found`);
273
+ }
274
+ return user;
275
+ }
276
+
277
+ async create(dto: CreateUserDto): Promise<User> {
278
+ const user = this.userRepo.create(dto);
279
+ return this.userRepo.save(user);
280
+ }
281
+ }
282
+ ```
283
+
284
+ ### 4. 中间件 (Middleware)
285
+
286
+ 在路由处理器之前执行,可访问请求/响应对象。
287
+
288
+ ```typescript
289
+ import { Injectable, NestMiddleware } from '@nestjs/common';
290
+ import { Request, Response, NextFunction } from 'express';
291
+
292
+ @Injectable()
293
+ export class LoggerMiddleware implements NestMiddleware {
294
+ use(req: Request, res: Response, next: NextFunction) {
295
+ const start = Date.now();
296
+ res.on('finish', () => {
297
+ const duration = Date.now() - start;
298
+ console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);
299
+ });
300
+ next();
301
+ }
302
+ }
303
+
304
+ // 在模块中注册
305
+ @Module({})
306
+ export class AppModule implements NestModule {
307
+ configure(consumer: MiddlewareConsumer) {
308
+ consumer
309
+ .apply(LoggerMiddleware, CorsMiddleware)
310
+ .exclude({ path: 'health', method: RequestMethod.GET })
311
+ .forRoutes('*');
312
+ }
313
+ }
314
+
315
+ // 函数式中间件(简单场景)
316
+ export function helmet(req: Request, res: Response, next: NextFunction) {
317
+ // 安全头设置
318
+ next();
319
+ }
320
+ ```
321
+
322
+ ### 5. 管道 (Pipes)
323
+
324
+ 用于数据转换和验证。在路由处理器执行之前处理参数。
325
+
326
+ ```typescript
327
+ import {
328
+ PipeTransform, Injectable, ArgumentMetadata,
329
+ BadRequestException,
330
+ } from '@nestjs/common';
331
+ import { validate } from 'class-validator';
332
+ import { plainToInstance } from 'class-transformer';
333
+
334
+ // 全局验证管道(推荐在 main.ts 设置)
335
+ async function bootstrap() {
336
+ const app = await NestFactory.create(AppModule);
337
+ app.useGlobalPipes(new ValidationPipe({
338
+ whitelist: true, // 剥离非 DTO 定义的属性
339
+ forbidNonWhitelisted: true, // 存在非白名单属性时抛出异常
340
+ transform: true, // 自动类型转换
341
+ transformOptions: {
342
+ enableImplicitConversion: true,
343
+ },
344
+ }));
345
+ await app.listen(3000);
346
+ }
347
+
348
+ // 自定义管道
349
+ @Injectable()
350
+ export class ParseDatePipe implements PipeTransform<string, Date> {
351
+ transform(value: string, metadata: ArgumentMetadata): Date {
352
+ const date = new Date(value);
353
+ if (isNaN(date.getTime())) {
354
+ throw new BadRequestException(`"${value}" is not a valid date`);
355
+ }
356
+ return date;
357
+ }
358
+ }
359
+
360
+ // DTO 验证示例
361
+ import { IsString, IsEmail, MinLength, IsOptional, IsEnum } from 'class-validator';
362
+
363
+ export class CreateUserDto {
364
+ @IsString()
365
+ @MinLength(2)
366
+ name: string;
367
+
368
+ @IsEmail()
369
+ email: string;
370
+
371
+ @IsString()
372
+ @MinLength(8)
373
+ password: string;
374
+
375
+ @IsOptional()
376
+ @IsEnum(UserRole)
377
+ role?: UserRole;
378
+ }
379
+ ```
380
+
381
+ ### 6. 守卫 (Guards)
382
+
383
+ 决定请求是否被路由处理器处理。用于认证和授权。
384
+
385
+ ```typescript
386
+ import {
387
+ Injectable, CanActivate, ExecutionContext,
388
+ SetMetadata, UseGuards, applyDecorators,
389
+ } from '@nestjs/common';
390
+ import { Reflector } from '@nestjs/core';
391
+
392
+ // 角色守卫
393
+ @Injectable()
394
+ export class RolesGuard implements CanActivate {
395
+ constructor(private reflector: Reflector) {}
396
+
397
+ canActivate(context: ExecutionContext): boolean {
398
+ const requiredRoles = this.reflector.getAllAndOverride<Role[]>('roles', [
399
+ context.getHandler(),
400
+ context.getClass(),
401
+ ]);
402
+ if (!requiredRoles) return true;
403
+
404
+ const { user } = context.switchToHttp().getRequest();
405
+ return requiredRoles.some((role) => user.roles?.includes(role));
406
+ }
407
+ }
408
+
409
+ // 角色装饰器
410
+ export const Roles = (...roles: Role[]) => SetMetadata('roles', roles);
411
+
412
+ // 组合装饰器(推荐模式)
413
+ export function Auth(...roles: Role[]) {
414
+ return applyDecorators(
415
+ Roles(...roles),
416
+ UseGuards(JwtAuthGuard, RolesGuard),
417
+ );
418
+ }
419
+
420
+ // 使用
421
+ @Controller('admin')
422
+ export class AdminController {
423
+ @Get('dashboard')
424
+ @Auth(Role.ADMIN)
425
+ getDashboard() {
426
+ return { message: 'Admin dashboard' };
427
+ }
428
+ }
429
+ ```
430
+
431
+ ### 7. 拦截器 (Interceptors)
432
+
433
+ 在路由处理器之前/之后执行额外逻辑。可用于日志、缓存、响应映射、超时等。
434
+
435
+ ```typescript
436
+ import {
437
+ Injectable, NestInterceptor, ExecutionContext, CallHandler,
438
+ } from '@nestjs/common';
439
+ import { Observable, map, tap, timeout, catchError } from 'rxjs';
440
+
441
+ // 响应包装拦截器
442
+ @Injectable()
443
+ export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> {
444
+ intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> {
445
+ return next.handle().pipe(
446
+ map((data) => ({
447
+ statusCode: context.switchToHttp().getResponse().statusCode,
448
+ data,
449
+ timestamp: new Date().toISOString(),
450
+ })),
451
+ );
452
+ }
453
+ }
454
+
455
+ // 日志拦截器
456
+ @Injectable()
457
+ export class LoggingInterceptor implements NestInterceptor {
458
+ private readonly logger = new Logger(LoggingInterceptor.name);
459
+
460
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
461
+ const req = context.switchToHttp().getRequest();
462
+ const { method, url } = req;
463
+ const now = Date.now();
464
+
465
+ return next.handle().pipe(
466
+ tap(() => this.logger.log(`${method} ${url} - ${Date.now() - now}ms`)),
467
+ );
468
+ }
469
+ }
470
+
471
+ // 超时拦截器
472
+ @Injectable()
473
+ export class TimeoutInterceptor implements NestInterceptor {
474
+ intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
475
+ return next.handle().pipe(
476
+ timeout(5000),
477
+ catchError((err) => {
478
+ if (err.name === 'TimeoutError') {
479
+ throw new RequestTimeoutException();
480
+ }
481
+ throw err;
482
+ }),
483
+ );
484
+ }
485
+ }
486
+ ```
487
+
488
+ ### 8. 异常过滤器 (Exception Filters)
489
+
490
+ 捕获并处理未处理的异常,统一错误响应格式。
491
+
492
+ ```typescript
493
+ import {
494
+ ExceptionFilter, Catch, ArgumentsHost,
495
+ HttpException, HttpStatus, Logger,
496
+ } from '@nestjs/common';
497
+ import { Request, Response } from 'express';
498
+
499
+ @Catch()
500
+ export class AllExceptionsFilter implements ExceptionFilter {
501
+ private readonly logger = new Logger(AllExceptionsFilter.name);
502
+
503
+ catch(exception: unknown, host: ArgumentsHost) {
504
+ const ctx = host.switchToHttp();
505
+ const response = ctx.getResponse<Response>();
506
+ const request = ctx.getRequest<Request>();
507
+
508
+ const status =
509
+ exception instanceof HttpException
510
+ ? exception.getStatus()
511
+ : HttpStatus.INTERNAL_SERVER_ERROR;
512
+
513
+ const message =
514
+ exception instanceof HttpException
515
+ ? exception.getResponse()
516
+ : 'Internal server error';
517
+
518
+ const errorResponse = {
519
+ statusCode: status,
520
+ timestamp: new Date().toISOString(),
521
+ path: request.url,
522
+ method: request.method,
523
+ message: typeof message === 'string' ? message : (message as any).message,
524
+ };
525
+
526
+ this.logger.error(
527
+ `${request.method} ${request.url} ${status}`,
528
+ exception instanceof Error ? exception.stack : '',
529
+ );
530
+
531
+ response.status(status).json(errorResponse);
532
+ }
533
+ }
534
+
535
+ // 自定义业务异常
536
+ export class BusinessException extends HttpException {
537
+ constructor(code: string, message: string, status = HttpStatus.BAD_REQUEST) {
538
+ super({ code, message }, status);
539
+ }
540
+ }
541
+ ```
542
+
543
+ ---
544
+
545
+ ## 依赖注入系统
546
+
547
+ ### 提供者作用域
548
+
549
+ ```typescript
550
+ import { Injectable, Scope } from '@nestjs/common';
551
+
552
+ // 默认: 单例(推荐,整个应用生命周期只创建一个实例)
553
+ @Injectable()
554
+ export class SingletonService {}
555
+
556
+ // 请求作用域(每个请求创建新实例,注意性能影响)
557
+ @Injectable({ scope: Scope.REQUEST })
558
+ export class RequestScopedService {
559
+ constructor(@Inject(REQUEST) private request: Request) {}
560
+ }
561
+
562
+ // 瞬态作用域(每次注入创建新实例)
563
+ @Injectable({ scope: Scope.TRANSIENT })
564
+ export class TransientService {}
565
+ ```
566
+
567
+ > **性能警告**: 请求作用域会导致依赖链上的所有提供者都变为请求作用域,显著增加实例化开销。除非确实需要访问请求对象,否则使用默认单例作用域。
568
+
569
+ ### 自定义提供者
570
+
571
+ ```typescript
572
+ @Module({
573
+ providers: [
574
+ // useClass — 标准类提供者
575
+ { provide: UsersService, useClass: UsersService },
576
+
577
+ // useValue — 值提供者(常量、配置、Mock)
578
+ { provide: 'API_KEY', useValue: process.env.API_KEY },
579
+ { provide: 'CONFIG', useValue: { retries: 3, timeout: 5000 } },
580
+
581
+ // useFactory — 工厂提供者(异步初始化、条件逻辑)
582
+ {
583
+ provide: 'ASYNC_CONNECTION',
584
+ useFactory: async (configService: ConfigService) => {
585
+ const conn = await createConnection(configService.get('DATABASE_URL'));
586
+ return conn;
587
+ },
588
+ inject: [ConfigService],
589
+ },
590
+
591
+ // useExisting — 别名提供者
592
+ { provide: 'AliasedService', useExisting: UsersService },
593
+ ],
594
+ })
595
+ export class AppModule {}
596
+ ```
597
+
598
+ ### 循环依赖解决
599
+
600
+ ```typescript
601
+ // 方法 1: forwardRef(推荐)
602
+ @Injectable()
603
+ export class CatsService {
604
+ constructor(
605
+ @Inject(forwardRef(() => DogsService))
606
+ private dogsService: DogsService,
607
+ ) {}
608
+ }
609
+
610
+ @Injectable()
611
+ export class DogsService {
612
+ constructor(
613
+ @Inject(forwardRef(() => CatsService))
614
+ private catsService: CatsService,
615
+ ) {}
616
+ }
617
+
618
+ // 模块级别同理
619
+ @Module({
620
+ imports: [forwardRef(() => DogsModule)],
621
+ })
622
+ export class CatsModule {}
623
+
624
+ // 方法 2: ModuleRef(运行时解析,避免循环)
625
+ @Injectable()
626
+ export class CatsService implements OnModuleInit {
627
+ private dogsService: DogsService;
628
+
629
+ constructor(private moduleRef: ModuleRef) {}
630
+
631
+ onModuleInit() {
632
+ this.dogsService = this.moduleRef.get(DogsService, { strict: false });
633
+ }
634
+ }
635
+ ```
636
+
637
+ > **最佳实践**: 循环依赖通常是架构设计的坏味道。优先考虑提取公共逻辑到第三个服务,或使用事件驱动模式解耦。
638
+
639
+ ---
640
+
641
+ ## 数据库集成
642
+
643
+ ### TypeORM 集成
644
+
645
+ ```bash
646
+ npm i @nestjs/typeorm typeorm pg
647
+ ```
648
+
649
+ ```typescript
650
+ // app.module.ts
651
+ @Module({
652
+ imports: [
653
+ TypeOrmModule.forRootAsync({
654
+ imports: [ConfigModule],
655
+ inject: [ConfigService],
656
+ useFactory: (config: ConfigService) => ({
657
+ type: 'postgres',
658
+ host: config.get('DB_HOST'),
659
+ port: config.get<number>('DB_PORT', 5432),
660
+ username: config.get('DB_USER'),
661
+ password: config.get('DB_PASS'),
662
+ database: config.get('DB_NAME'),
663
+ entities: [__dirname + '/**/*.entity{.ts,.js}'],
664
+ synchronize: false, // 生产环境必须为 false
665
+ logging: config.get('NODE_ENV') === 'development',
666
+ migrations: [__dirname + '/migrations/*{.ts,.js}'],
667
+ }),
668
+ }),
669
+ ],
670
+ })
671
+ export class AppModule {}
672
+
673
+ // user.entity.ts
674
+ @Entity('users')
675
+ export class User {
676
+ @PrimaryGeneratedColumn('uuid')
677
+ id: string;
678
+
679
+ @Column({ unique: true })
680
+ email: string;
681
+
682
+ @Column()
683
+ name: string;
684
+
685
+ @Column({ select: false })
686
+ password: string;
687
+
688
+ @OneToMany(() => Order, (order) => order.user)
689
+ orders: Order[];
690
+
691
+ @CreateDateColumn()
692
+ createdAt: Date;
693
+
694
+ @UpdateDateColumn()
695
+ updatedAt: Date;
696
+ }
697
+
698
+ // users.module.ts
699
+ @Module({
700
+ imports: [TypeOrmModule.forFeature([User])],
701
+ providers: [UsersService],
702
+ controllers: [UsersController],
703
+ })
704
+ export class UsersModule {}
705
+
706
+ // users.service.ts (Repository 模式)
707
+ @Injectable()
708
+ export class UsersService {
709
+ constructor(
710
+ @InjectRepository(User)
711
+ private readonly userRepo: Repository<User>,
712
+ ) {}
713
+
714
+ async findByEmail(email: string): Promise<User | null> {
715
+ return this.userRepo.findOne({
716
+ where: { email },
717
+ relations: ['orders'],
718
+ });
719
+ }
720
+ }
721
+ ```
722
+
723
+ ### TypeORM 迁移
724
+
725
+ ```bash
726
+ # 生成迁移
727
+ npx typeorm migration:generate -d src/data-source.ts src/migrations/AddUserTable
728
+
729
+ # 运行迁移
730
+ npx typeorm migration:run -d src/data-source.ts
731
+
732
+ # 回滚
733
+ npx typeorm migration:revert -d src/data-source.ts
734
+ ```
735
+
736
+ ### TypeORM 事务
737
+
738
+ ```typescript
739
+ @Injectable()
740
+ export class OrdersService {
741
+ constructor(private readonly dataSource: DataSource) {}
742
+
743
+ async createOrder(userId: string, items: OrderItemDto[]): Promise<Order> {
744
+ const queryRunner = this.dataSource.createQueryRunner();
745
+ await queryRunner.connect();
746
+ await queryRunner.startTransaction();
747
+
748
+ try {
749
+ const order = queryRunner.manager.create(Order, { userId });
750
+ const savedOrder = await queryRunner.manager.save(order);
751
+
752
+ for (const item of items) {
753
+ // 扣减库存
754
+ const product = await queryRunner.manager.findOne(Product, {
755
+ where: { id: item.productId },
756
+ lock: { mode: 'pessimistic_write' },
757
+ });
758
+ if (!product || product.stock < item.quantity) {
759
+ throw new BadRequestException(`Insufficient stock for product ${item.productId}`);
760
+ }
761
+ product.stock -= item.quantity;
762
+ await queryRunner.manager.save(product);
763
+
764
+ // 创建订单项
765
+ const orderItem = queryRunner.manager.create(OrderItem, {
766
+ orderId: savedOrder.id, ...item,
767
+ });
768
+ await queryRunner.manager.save(orderItem);
769
+ }
770
+
771
+ await queryRunner.commitTransaction();
772
+ return savedOrder;
773
+ } catch (err) {
774
+ await queryRunner.rollbackTransaction();
775
+ throw err;
776
+ } finally {
777
+ await queryRunner.release();
778
+ }
779
+ }
780
+ }
781
+ ```
782
+
783
+ ### Prisma 集成
784
+
785
+ ```bash
786
+ npm i prisma @prisma/client
787
+ npx prisma init
788
+ ```
789
+
790
+ ```typescript
791
+ // prisma.service.ts
792
+ @Injectable()
793
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
794
+ async onModuleInit() {
795
+ await this.$connect();
796
+ }
797
+
798
+ async onModuleDestroy() {
799
+ await this.$disconnect();
800
+ }
801
+
802
+ // 清理用于测试
803
+ async cleanDatabase() {
804
+ if (process.env.NODE_ENV !== 'test') {
805
+ throw new Error('cleanDatabase is only for test environment');
806
+ }
807
+ const models = Reflect.ownKeys(this).filter((key) => typeof key === 'string' && !key.startsWith('_'));
808
+ return Promise.all(
809
+ models.map((model) => (this as any)[model]?.deleteMany?.()),
810
+ );
811
+ }
812
+ }
813
+
814
+ // prisma.module.ts
815
+ @Global()
816
+ @Module({
817
+ providers: [PrismaService],
818
+ exports: [PrismaService],
819
+ })
820
+ export class PrismaModule {}
821
+
822
+ // users.service.ts (Prisma)
823
+ @Injectable()
824
+ export class UsersService {
825
+ constructor(private readonly prisma: PrismaService) {}
826
+
827
+ async findAll(params: { skip?: number; take?: number; where?: Prisma.UserWhereInput }) {
828
+ const { skip, take, where } = params;
829
+ return this.prisma.user.findMany({ skip, take, where, include: { orders: true } });
830
+ }
831
+
832
+ // Prisma 事务
833
+ async transferCredits(fromId: string, toId: string, amount: number) {
834
+ return this.prisma.$transaction(async (tx) => {
835
+ const sender = await tx.user.update({
836
+ where: { id: fromId },
837
+ data: { credits: { decrement: amount } },
838
+ });
839
+ if (sender.credits < 0) {
840
+ throw new BadRequestException('Insufficient credits');
841
+ }
842
+ await tx.user.update({
843
+ where: { id: toId },
844
+ data: { credits: { increment: amount } },
845
+ });
846
+ });
847
+ }
848
+ }
849
+ ```
850
+
851
+ ---
852
+
853
+ ## 认证与授权
854
+
855
+ ### Passport + JWT 认证
856
+
857
+ ```bash
858
+ npm i @nestjs/passport passport passport-local passport-jwt @nestjs/jwt
859
+ npm i -D @types/passport-local @types/passport-jwt
860
+ ```
861
+
862
+ ```typescript
863
+ // auth.module.ts
864
+ @Module({
865
+ imports: [
866
+ UsersModule,
867
+ PassportModule.register({ defaultStrategy: 'jwt' }),
868
+ JwtModule.registerAsync({
869
+ imports: [ConfigModule],
870
+ inject: [ConfigService],
871
+ useFactory: (config: ConfigService) => ({
872
+ secret: config.get('JWT_SECRET'),
873
+ signOptions: { expiresIn: '15m' },
874
+ }),
875
+ }),
876
+ ],
877
+ providers: [AuthService, LocalStrategy, JwtStrategy],
878
+ controllers: [AuthController],
879
+ exports: [AuthService],
880
+ })
881
+ export class AuthModule {}
882
+
883
+ // jwt.strategy.ts
884
+ @Injectable()
885
+ export class JwtStrategy extends PassportStrategy(Strategy) {
886
+ constructor(
887
+ private configService: ConfigService,
888
+ private usersService: UsersService,
889
+ ) {
890
+ super({
891
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
892
+ ignoreExpiration: false,
893
+ secretOrKey: configService.get('JWT_SECRET'),
894
+ });
895
+ }
896
+
897
+ async validate(payload: JwtPayload): Promise<User> {
898
+ const user = await this.usersService.findOne(payload.sub);
899
+ if (!user) throw new UnauthorizedException();
900
+ return user;
901
+ }
902
+ }
903
+
904
+ // auth.service.ts
905
+ @Injectable()
906
+ export class AuthService {
907
+ constructor(
908
+ private usersService: UsersService,
909
+ private jwtService: JwtService,
910
+ ) {}
911
+
912
+ async validateUser(email: string, password: string): Promise<User | null> {
913
+ const user = await this.usersService.findByEmail(email);
914
+ if (user && (await bcrypt.compare(password, user.password))) {
915
+ return user;
916
+ }
917
+ return null;
918
+ }
919
+
920
+ async login(user: User) {
921
+ const payload: JwtPayload = { sub: user.id, email: user.email, roles: user.roles };
922
+ return {
923
+ accessToken: this.jwtService.sign(payload),
924
+ refreshToken: this.jwtService.sign(payload, { expiresIn: '7d' }),
925
+ };
926
+ }
927
+
928
+ async refreshToken(token: string) {
929
+ try {
930
+ const payload = this.jwtService.verify(token);
931
+ const user = await this.usersService.findOne(payload.sub);
932
+ if (!user) throw new UnauthorizedException();
933
+ return this.login(user);
934
+ } catch {
935
+ throw new UnauthorizedException('Invalid refresh token');
936
+ }
937
+ }
938
+ }
939
+ ```
940
+
941
+ ### RBAC(基于角色的访问控制)
942
+
943
+ ```typescript
944
+ export enum Role {
945
+ USER = 'user',
946
+ ADMIN = 'admin',
947
+ MODERATOR = 'moderator',
948
+ }
949
+
950
+ // roles.decorator.ts
951
+ export const ROLES_KEY = 'roles';
952
+ export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);
953
+
954
+ // roles.guard.ts
955
+ @Injectable()
956
+ export class RolesGuard implements CanActivate {
957
+ constructor(private reflector: Reflector) {}
958
+
959
+ canActivate(context: ExecutionContext): boolean {
960
+ const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
961
+ context.getHandler(),
962
+ context.getClass(),
963
+ ]);
964
+ if (!requiredRoles) return true;
965
+ const { user } = context.switchToHttp().getRequest();
966
+ return requiredRoles.some((role) => user.roles?.includes(role));
967
+ }
968
+ }
969
+
970
+ // 使用
971
+ @Controller('posts')
972
+ @UseGuards(JwtAuthGuard, RolesGuard)
973
+ export class PostsController {
974
+ @Delete(':id')
975
+ @Roles(Role.ADMIN, Role.MODERATOR)
976
+ remove(@Param('id') id: string) {
977
+ return this.postsService.remove(id);
978
+ }
979
+ }
980
+ ```
981
+
982
+ ### CASL 权限管理
983
+
984
+ ```bash
985
+ npm i @casl/ability
986
+ ```
987
+
988
+ ```typescript
989
+ // casl-ability.factory.ts
990
+ @Injectable()
991
+ export class CaslAbilityFactory {
992
+ createForUser(user: User) {
993
+ const { can, cannot, build } = new AbilityBuilder<Ability>(Ability);
994
+
995
+ if (user.roles.includes(Role.ADMIN)) {
996
+ can('manage', 'all');
997
+ } else {
998
+ can('read', 'Article');
999
+ can('create', 'Article');
1000
+ can('update', 'Article', { authorId: user.id }); // 只能编辑自己的文章
1001
+ cannot('delete', 'Article');
1002
+ }
1003
+
1004
+ return build();
1005
+ }
1006
+ }
1007
+
1008
+ // policies.guard.ts
1009
+ @Injectable()
1010
+ export class PoliciesGuard implements CanActivate {
1011
+ constructor(
1012
+ private reflector: Reflector,
1013
+ private caslAbilityFactory: CaslAbilityFactory,
1014
+ ) {}
1015
+
1016
+ canActivate(context: ExecutionContext): boolean {
1017
+ const policyHandlers = this.reflector.get<PolicyHandler[]>('check_policies', context.getHandler()) || [];
1018
+ const { user } = context.switchToHttp().getRequest();
1019
+ const ability = this.caslAbilityFactory.createForUser(user);
1020
+ return policyHandlers.every((handler) => handler(ability));
1021
+ }
1022
+ }
1023
+ ```
1024
+
1025
+ ---
1026
+
1027
+ ## WebSocket
1028
+
1029
+ ### Gateway 基础
1030
+
1031
+ ```bash
1032
+ npm i @nestjs/websockets @nestjs/platform-socket.io socket.io
1033
+ ```
1034
+
1035
+ ```typescript
1036
+ import {
1037
+ WebSocketGateway, WebSocketServer,
1038
+ SubscribeMessage, MessageBody,
1039
+ ConnectedSocket, OnGatewayInit,
1040
+ OnGatewayConnection, OnGatewayDisconnect,
1041
+ WsException,
1042
+ } from '@nestjs/websockets';
1043
+ import { Server, Socket } from 'socket.io';
1044
+
1045
+ @WebSocketGateway({
1046
+ cors: { origin: '*' },
1047
+ namespace: '/chat',
1048
+ })
1049
+ export class ChatGateway
1050
+ implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
1051
+ {
1052
+ @WebSocketServer()
1053
+ server: Server;
1054
+
1055
+ private readonly logger = new Logger(ChatGateway.name);
1056
+
1057
+ afterInit(server: Server) {
1058
+ this.logger.log('WebSocket Gateway initialized');
1059
+ }
1060
+
1061
+ handleConnection(client: Socket) {
1062
+ this.logger.log(`Client connected: ${client.id}`);
1063
+ }
1064
+
1065
+ handleDisconnect(client: Socket) {
1066
+ this.logger.log(`Client disconnected: ${client.id}`);
1067
+ }
1068
+
1069
+ @SubscribeMessage('sendMessage')
1070
+ handleMessage(
1071
+ @MessageBody() data: { room: string; message: string },
1072
+ @ConnectedSocket() client: Socket,
1073
+ ) {
1074
+ // 向房间广播(不包括发送者)
1075
+ client.to(data.room).emit('newMessage', {
1076
+ sender: client.id,
1077
+ message: data.message,
1078
+ timestamp: new Date(),
1079
+ });
1080
+ return { event: 'messageSent', data: { success: true } };
1081
+ }
1082
+
1083
+ @SubscribeMessage('joinRoom')
1084
+ handleJoinRoom(
1085
+ @MessageBody() room: string,
1086
+ @ConnectedSocket() client: Socket,
1087
+ ) {
1088
+ client.join(room);
1089
+ this.server.to(room).emit('userJoined', { userId: client.id });
1090
+ }
1091
+
1092
+ @SubscribeMessage('leaveRoom')
1093
+ handleLeaveRoom(
1094
+ @MessageBody() room: string,
1095
+ @ConnectedSocket() client: Socket,
1096
+ ) {
1097
+ client.leave(room);
1098
+ this.server.to(room).emit('userLeft', { userId: client.id });
1099
+ }
1100
+ }
1101
+ ```
1102
+
1103
+ ### WebSocket 认证
1104
+
1105
+ ```typescript
1106
+ @WebSocketGateway()
1107
+ export class AuthenticatedGateway {
1108
+ @WebSocketServer() server: Server;
1109
+
1110
+ afterInit(server: Server) {
1111
+ server.use(async (socket: Socket, next) => {
1112
+ try {
1113
+ const token = socket.handshake.auth.token
1114
+ || socket.handshake.headers.authorization?.split(' ')[1];
1115
+ if (!token) throw new WsException('Missing token');
1116
+ const payload = this.jwtService.verify(token);
1117
+ socket.data.user = payload;
1118
+ next();
1119
+ } catch (err) {
1120
+ next(new Error('Unauthorized'));
1121
+ }
1122
+ });
1123
+ }
1124
+ }
1125
+ ```
1126
+
1127
+ ---
1128
+
1129
+ ## 微服务
1130
+
1131
+ ### Transport 层概览
1132
+
1133
+ NestJS 微服务抽象了通信层,支持多种传输协议:
1134
+
1135
+ ```typescript
1136
+ // TCP(默认)
1137
+ const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
1138
+ transport: Transport.TCP,
1139
+ options: { host: '0.0.0.0', port: 3001 },
1140
+ });
1141
+
1142
+ // Redis
1143
+ const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
1144
+ transport: Transport.REDIS,
1145
+ options: { host: 'localhost', port: 6379 },
1146
+ });
1147
+
1148
+ // Kafka
1149
+ const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
1150
+ transport: Transport.KAFKA,
1151
+ options: {
1152
+ client: { brokers: ['localhost:9092'], clientId: 'orders-service' },
1153
+ consumer: { groupId: 'orders-consumer' },
1154
+ },
1155
+ });
1156
+
1157
+ // gRPC
1158
+ const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
1159
+ transport: Transport.GRPC,
1160
+ options: {
1161
+ package: 'orders',
1162
+ protoPath: join(__dirname, 'orders.proto'),
1163
+ url: '0.0.0.0:50051',
1164
+ },
1165
+ });
1166
+ ```
1167
+
1168
+ ### 消息模式与事件
1169
+
1170
+ ```typescript
1171
+ // 微服务端 — 处理消息
1172
+ @Controller()
1173
+ export class OrdersController {
1174
+ // 请求-响应模式(同步通信)
1175
+ @MessagePattern({ cmd: 'get_order' })
1176
+ getOrder(@Payload() data: { orderId: string }) {
1177
+ return this.ordersService.findOne(data.orderId);
1178
+ }
1179
+
1180
+ // 事件模式(异步通信,无回复)
1181
+ @EventPattern('order_created')
1182
+ handleOrderCreated(@Payload() data: OrderCreatedEvent) {
1183
+ this.notificationService.sendOrderConfirmation(data);
1184
+ }
1185
+ }
1186
+
1187
+ // 客户端 — 发送消息
1188
+ @Module({
1189
+ imports: [
1190
+ ClientsModule.register([{
1191
+ name: 'ORDERS_SERVICE',
1192
+ transport: Transport.REDIS,
1193
+ options: { host: 'localhost', port: 6379 },
1194
+ }]),
1195
+ ],
1196
+ })
1197
+ export class ApiGatewayModule {}
1198
+
1199
+ @Injectable()
1200
+ export class ApiGatewayService {
1201
+ constructor(@Inject('ORDERS_SERVICE') private ordersClient: ClientProxy) {}
1202
+
1203
+ getOrder(orderId: string): Observable<Order> {
1204
+ return this.ordersClient.send({ cmd: 'get_order' }, { orderId });
1205
+ }
1206
+
1207
+ createOrder(dto: CreateOrderDto) {
1208
+ this.ordersClient.emit('order_created', dto); // 单向事件
1209
+ }
1210
+ }
1211
+ ```
1212
+
1213
+ ### 混合应用(HTTP + 微服务)
1214
+
1215
+ ```typescript
1216
+ async function bootstrap() {
1217
+ const app = await NestFactory.create(AppModule);
1218
+
1219
+ // 同时连接 Redis 和 Kafka 微服务
1220
+ app.connectMicroservice<MicroserviceOptions>({
1221
+ transport: Transport.REDIS,
1222
+ options: { host: 'localhost', port: 6379 },
1223
+ });
1224
+ app.connectMicroservice<MicroserviceOptions>({
1225
+ transport: Transport.KAFKA,
1226
+ options: {
1227
+ client: { brokers: ['localhost:9092'] },
1228
+ consumer: { groupId: 'hybrid-consumer' },
1229
+ },
1230
+ });
1231
+
1232
+ await app.startAllMicroservices();
1233
+ await app.listen(3000);
1234
+ }
1235
+ ```
1236
+
1237
+ ---
1238
+
1239
+ ## GraphQL
1240
+
1241
+ ### Code-First 方式
1242
+
1243
+ ```bash
1244
+ npm i @nestjs/graphql @nestjs/apollo @apollo/server graphql
1245
+ ```
1246
+
1247
+ ```typescript
1248
+ // app.module.ts
1249
+ @Module({
1250
+ imports: [
1251
+ GraphQLModule.forRoot<ApolloDriverConfig>({
1252
+ driver: ApolloDriver,
1253
+ autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
1254
+ sortSchema: true,
1255
+ playground: process.env.NODE_ENV !== 'production',
1256
+ context: ({ req }) => ({ req }),
1257
+ }),
1258
+ ],
1259
+ })
1260
+ export class AppModule {}
1261
+
1262
+ // user.model.ts
1263
+ @ObjectType()
1264
+ export class UserModel {
1265
+ @Field(() => ID)
1266
+ id: string;
1267
+
1268
+ @Field()
1269
+ email: string;
1270
+
1271
+ @Field()
1272
+ name: string;
1273
+
1274
+ @Field(() => [OrderModel], { nullable: true })
1275
+ orders?: OrderModel[];
1276
+
1277
+ @Field()
1278
+ createdAt: Date;
1279
+ }
1280
+
1281
+ // users.resolver.ts
1282
+ @Resolver(() => UserModel)
1283
+ export class UsersResolver {
1284
+ constructor(private readonly usersService: UsersService) {}
1285
+
1286
+ @Query(() => [UserModel], { name: 'users' })
1287
+ findAll(
1288
+ @Args('page', { type: () => Int, defaultValue: 1 }) page: number,
1289
+ ) {
1290
+ return this.usersService.findAll(page);
1291
+ }
1292
+
1293
+ @Query(() => UserModel, { name: 'user' })
1294
+ findOne(@Args('id', { type: () => ID }) id: string) {
1295
+ return this.usersService.findOne(id);
1296
+ }
1297
+
1298
+ @Mutation(() => UserModel)
1299
+ createUser(@Args('input') input: CreateUserInput) {
1300
+ return this.usersService.create(input);
1301
+ }
1302
+
1303
+ @ResolveField(() => [OrderModel])
1304
+ orders(@Parent() user: UserModel) {
1305
+ return this.ordersService.findByUserId(user.id);
1306
+ }
1307
+ }
1308
+ ```
1309
+
1310
+ ### DataLoader(N+1 问题解决)
1311
+
1312
+ ```typescript
1313
+ import DataLoader from 'dataloader';
1314
+
1315
+ @Injectable({ scope: Scope.REQUEST })
1316
+ export class OrdersLoader {
1317
+ constructor(private readonly ordersService: OrdersService) {}
1318
+
1319
+ readonly batchByUserId = new DataLoader<string, Order[]>(async (userIds: string[]) => {
1320
+ const orders = await this.ordersService.findByUserIds([...userIds]);
1321
+ const ordersMap = new Map<string, Order[]>();
1322
+ orders.forEach((order) => {
1323
+ const existing = ordersMap.get(order.userId) || [];
1324
+ existing.push(order);
1325
+ ordersMap.set(order.userId, existing);
1326
+ });
1327
+ return userIds.map((id) => ordersMap.get(id) || []);
1328
+ });
1329
+ }
1330
+
1331
+ // resolver 中使用
1332
+ @ResolveField(() => [OrderModel])
1333
+ orders(@Parent() user: UserModel) {
1334
+ return this.ordersLoader.batchByUserId.load(user.id);
1335
+ }
1336
+ ```
1337
+
1338
+ ### 订阅 (Subscriptions)
1339
+
1340
+ ```typescript
1341
+ // app.module.ts 启用订阅
1342
+ GraphQLModule.forRoot<ApolloDriverConfig>({
1343
+ driver: ApolloDriver,
1344
+ autoSchemaFile: true,
1345
+ subscriptions: {
1346
+ 'graphql-ws': true, // 推荐:graphql-ws 协议
1347
+ 'subscriptions-transport-ws': false,
1348
+ },
1349
+ });
1350
+
1351
+ // resolver
1352
+ @Resolver()
1353
+ export class MessagesResolver {
1354
+ @Subscription(() => MessageModel, {
1355
+ filter: (payload, variables) =>
1356
+ payload.messageAdded.channelId === variables.channelId,
1357
+ })
1358
+ messageAdded(@Args('channelId') channelId: string) {
1359
+ return pubSub.asyncIterator('messageAdded');
1360
+ }
1361
+
1362
+ @Mutation(() => MessageModel)
1363
+ async sendMessage(@Args('input') input: SendMessageInput) {
1364
+ const message = await this.messagesService.create(input);
1365
+ pubSub.publish('messageAdded', { messageAdded: message });
1366
+ return message;
1367
+ }
1368
+ }
1369
+ ```
1370
+
1371
+ ---
1372
+
1373
+ ## 队列处理
1374
+
1375
+ ### Bull / BullMQ 集成
1376
+
1377
+ ```bash
1378
+ npm i @nestjs/bullmq bullmq
1379
+ ```
1380
+
1381
+ ```typescript
1382
+ // app.module.ts
1383
+ @Module({
1384
+ imports: [
1385
+ BullModule.forRoot({
1386
+ connection: { host: 'localhost', port: 6379 },
1387
+ }),
1388
+ BullModule.registerQueue(
1389
+ { name: 'email' },
1390
+ { name: 'report' },
1391
+ ),
1392
+ ],
1393
+ })
1394
+ export class AppModule {}
1395
+
1396
+ // email.producer.ts
1397
+ @Injectable()
1398
+ export class EmailService {
1399
+ constructor(@InjectQueue('email') private emailQueue: Queue) {}
1400
+
1401
+ async sendWelcomeEmail(userId: string) {
1402
+ await this.emailQueue.add('welcome', { userId }, {
1403
+ delay: 5000, // 延迟 5 秒发送
1404
+ attempts: 3, // 失败重试 3 次
1405
+ backoff: { type: 'exponential', delay: 2000 },
1406
+ removeOnComplete: 100, // 保留最近 100 个完成任务
1407
+ removeOnFail: 500, // 保留最近 500 个失败任务
1408
+ });
1409
+ }
1410
+
1411
+ async sendBulkEmails(userIds: string[]) {
1412
+ const jobs = userIds.map((userId) => ({
1413
+ name: 'bulk',
1414
+ data: { userId },
1415
+ opts: { priority: 10 },
1416
+ }));
1417
+ await this.emailQueue.addBulk(jobs);
1418
+ }
1419
+ }
1420
+
1421
+ // email.consumer.ts
1422
+ @Processor('email')
1423
+ export class EmailConsumer extends WorkerHost {
1424
+ private readonly logger = new Logger(EmailConsumer.name);
1425
+
1426
+ async process(job: Job<{ userId: string }>): Promise<void> {
1427
+ switch (job.name) {
1428
+ case 'welcome':
1429
+ await this.sendWelcomeEmail(job.data.userId);
1430
+ break;
1431
+ case 'bulk':
1432
+ await this.sendBulkEmail(job.data.userId);
1433
+ break;
1434
+ }
1435
+ }
1436
+
1437
+ @OnWorkerEvent('completed')
1438
+ onCompleted(job: Job) {
1439
+ this.logger.log(`Job ${job.id} completed`);
1440
+ }
1441
+
1442
+ @OnWorkerEvent('failed')
1443
+ onFailed(job: Job, error: Error) {
1444
+ this.logger.error(`Job ${job.id} failed: ${error.message}`);
1445
+ }
1446
+
1447
+ private async sendWelcomeEmail(userId: string) {
1448
+ // 实际发送逻辑
1449
+ }
1450
+
1451
+ private async sendBulkEmail(userId: string) {
1452
+ // 批量发送逻辑
1453
+ }
1454
+ }
1455
+ ```
1456
+
1457
+ ---
1458
+
1459
+ ## 缓存
1460
+
1461
+ ### Redis 缓存集成
1462
+
1463
+ ```bash
1464
+ npm i @nestjs/cache-manager cache-manager cache-manager-ioredis-yet ioredis
1465
+ ```
1466
+
1467
+ ```typescript
1468
+ // app.module.ts
1469
+ @Module({
1470
+ imports: [
1471
+ CacheModule.registerAsync({
1472
+ isGlobal: true,
1473
+ imports: [ConfigModule],
1474
+ inject: [ConfigService],
1475
+ useFactory: (config: ConfigService) => ({
1476
+ store: redisStore,
1477
+ host: config.get('REDIS_HOST', 'localhost'),
1478
+ port: config.get('REDIS_PORT', 6379),
1479
+ ttl: 300, // 默认 5 分钟
1480
+ }),
1481
+ }),
1482
+ ],
1483
+ })
1484
+ export class AppModule {}
1485
+
1486
+ // 使用 CacheInterceptor(自动缓存 GET 请求)
1487
+ @Controller('products')
1488
+ @UseInterceptors(CacheInterceptor)
1489
+ export class ProductsController {
1490
+ @Get()
1491
+ @CacheTTL(600) // 覆盖默认 TTL,10 分钟
1492
+ @CacheKey('all_products')
1493
+ findAll() {
1494
+ return this.productsService.findAll();
1495
+ }
1496
+ }
1497
+
1498
+ // 手动缓存控制
1499
+ @Injectable()
1500
+ export class ProductsService {
1501
+ constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}
1502
+
1503
+ async findOne(id: string): Promise<Product> {
1504
+ const cacheKey = `product:${id}`;
1505
+ const cached = await this.cacheManager.get<Product>(cacheKey);
1506
+ if (cached) return cached;
1507
+
1508
+ const product = await this.productRepo.findOne({ where: { id } });
1509
+ if (product) {
1510
+ await this.cacheManager.set(cacheKey, product, 600);
1511
+ }
1512
+ return product;
1513
+ }
1514
+
1515
+ async update(id: string, dto: UpdateProductDto): Promise<Product> {
1516
+ const product = await this.productRepo.save({ id, ...dto });
1517
+ await this.cacheManager.del(`product:${id}`); // 失效缓存
1518
+ await this.cacheManager.del('all_products');
1519
+ return product;
1520
+ }
1521
+ }
1522
+ ```
1523
+
1524
+ ---
1525
+
1526
+ ## 测试
1527
+
1528
+ ### 单元测试
1529
+
1530
+ ```typescript
1531
+ import { Test, TestingModule } from '@nestjs/testing';
1532
+
1533
+ describe('UsersService', () => {
1534
+ let service: UsersService;
1535
+ let repo: Repository<User>;
1536
+
1537
+ beforeEach(async () => {
1538
+ const module: TestingModule = await Test.createTestingModule({
1539
+ providers: [
1540
+ UsersService,
1541
+ {
1542
+ provide: getRepositoryToken(User),
1543
+ useValue: {
1544
+ findOne: jest.fn(),
1545
+ find: jest.fn(),
1546
+ save: jest.fn(),
1547
+ create: jest.fn(),
1548
+ delete: jest.fn(),
1549
+ },
1550
+ },
1551
+ ],
1552
+ }).compile();
1553
+
1554
+ service = module.get<UsersService>(UsersService);
1555
+ repo = module.get<Repository<User>>(getRepositoryToken(User));
1556
+ });
1557
+
1558
+ describe('findOne', () => {
1559
+ it('should return a user', async () => {
1560
+ const user = { id: '1', name: 'Alice', email: 'alice@test.com' };
1561
+ jest.spyOn(repo, 'findOne').mockResolvedValue(user as User);
1562
+
1563
+ const result = await service.findOne('1');
1564
+ expect(result).toEqual(user);
1565
+ expect(repo.findOne).toHaveBeenCalledWith({ where: { id: '1' } });
1566
+ });
1567
+
1568
+ it('should throw NotFoundException if user not found', async () => {
1569
+ jest.spyOn(repo, 'findOne').mockResolvedValue(null);
1570
+
1571
+ await expect(service.findOne('999')).rejects.toThrow(NotFoundException);
1572
+ });
1573
+ });
1574
+ });
1575
+ ```
1576
+
1577
+ ### E2E 测试
1578
+
1579
+ ```typescript
1580
+ import { Test, TestingModule } from '@nestjs/testing';
1581
+ import { INestApplication, ValidationPipe } from '@nestjs/common';
1582
+ import * as request from 'supertest';
1583
+
1584
+ describe('UsersController (e2e)', () => {
1585
+ let app: INestApplication;
1586
+
1587
+ beforeAll(async () => {
1588
+ const moduleFixture: TestingModule = await Test.createTestingModule({
1589
+ imports: [AppModule],
1590
+ })
1591
+ .overrideProvider(UsersService)
1592
+ .useValue({
1593
+ findAll: jest.fn().mockResolvedValue([{ id: '1', name: 'Alice' }]),
1594
+ findOne: jest.fn().mockResolvedValue({ id: '1', name: 'Alice' }),
1595
+ create: jest.fn().mockResolvedValue({ id: '2', name: 'Bob' }),
1596
+ })
1597
+ .compile();
1598
+
1599
+ app = moduleFixture.createNestApplication();
1600
+ app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
1601
+ await app.init();
1602
+ });
1603
+
1604
+ afterAll(async () => {
1605
+ await app.close();
1606
+ });
1607
+
1608
+ describe('GET /users', () => {
1609
+ it('should return an array of users', () => {
1610
+ return request(app.getHttpServer())
1611
+ .get('/users')
1612
+ .expect(200)
1613
+ .expect((res) => {
1614
+ expect(res.body).toHaveLength(1);
1615
+ expect(res.body[0].name).toBe('Alice');
1616
+ });
1617
+ });
1618
+ });
1619
+
1620
+ describe('POST /users', () => {
1621
+ it('should create a user', () => {
1622
+ return request(app.getHttpServer())
1623
+ .post('/users')
1624
+ .send({ name: 'Bob', email: 'bob@test.com', password: 'securePass1' })
1625
+ .expect(201);
1626
+ });
1627
+
1628
+ it('should reject invalid input', () => {
1629
+ return request(app.getHttpServer())
1630
+ .post('/users')
1631
+ .send({ name: '' })
1632
+ .expect(400);
1633
+ });
1634
+ });
1635
+ });
1636
+ ```
1637
+
1638
+ ### Testing 模块高级用法
1639
+
1640
+ ```typescript
1641
+ // 自动 Mock 所有依赖
1642
+ const module = await Test.createTestingModule({
1643
+ providers: [UsersService],
1644
+ })
1645
+ .useMocker((token) => {
1646
+ if (typeof token === 'function') {
1647
+ return createMock(token); // 使用 @golevelup/ts-jest
1648
+ }
1649
+ return {};
1650
+ })
1651
+ .compile();
1652
+
1653
+ // 覆盖守卫
1654
+ const module = await Test.createTestingModule({
1655
+ imports: [AppModule],
1656
+ })
1657
+ .overrideGuard(JwtAuthGuard)
1658
+ .useValue({ canActivate: () => true })
1659
+ .compile();
1660
+
1661
+ // 覆盖拦截器
1662
+ const module = await Test.createTestingModule({
1663
+ imports: [AppModule],
1664
+ })
1665
+ .overrideInterceptor(CacheInterceptor)
1666
+ .useValue({ intercept: (_, next) => next.handle() })
1667
+ .compile();
1668
+ ```
1669
+
1670
+ ---
1671
+
1672
+ ## 部署
1673
+
1674
+ ### Docker
1675
+
1676
+ ```dockerfile
1677
+ # 多阶段构建
1678
+ FROM node:20-alpine AS builder
1679
+ WORKDIR /app
1680
+ COPY package*.json ./
1681
+ RUN npm ci
1682
+ COPY . .
1683
+ RUN npm run build
1684
+
1685
+ FROM node:20-alpine AS production
1686
+ WORKDIR /app
1687
+ COPY package*.json ./
1688
+ RUN npm ci --only=production && npm cache clean --force
1689
+ COPY --from=builder /app/dist ./dist
1690
+
1691
+ # 非 root 用户运行
1692
+ RUN addgroup -g 1001 -S nodejs && adduser -S nestjs -u 1001
1693
+ USER nestjs
1694
+
1695
+ EXPOSE 3000
1696
+ CMD ["node", "dist/main"]
1697
+ ```
1698
+
1699
+ ### Kubernetes
1700
+
1701
+ ```yaml
1702
+ apiVersion: apps/v1
1703
+ kind: Deployment
1704
+ metadata:
1705
+ name: nestjs-api
1706
+ spec:
1707
+ replicas: 3
1708
+ selector:
1709
+ matchLabels:
1710
+ app: nestjs-api
1711
+ template:
1712
+ metadata:
1713
+ labels:
1714
+ app: nestjs-api
1715
+ spec:
1716
+ containers:
1717
+ - name: api
1718
+ image: registry.example.com/nestjs-api:latest
1719
+ ports:
1720
+ - containerPort: 3000
1721
+ env:
1722
+ - name: NODE_ENV
1723
+ value: "production"
1724
+ - name: DATABASE_URL
1725
+ valueFrom:
1726
+ secretKeyRef:
1727
+ name: db-secrets
1728
+ key: url
1729
+ resources:
1730
+ requests:
1731
+ cpu: 100m
1732
+ memory: 256Mi
1733
+ limits:
1734
+ cpu: 500m
1735
+ memory: 512Mi
1736
+ livenessProbe:
1737
+ httpGet:
1738
+ path: /health
1739
+ port: 3000
1740
+ initialDelaySeconds: 30
1741
+ periodSeconds: 10
1742
+ readinessProbe:
1743
+ httpGet:
1744
+ path: /health
1745
+ port: 3000
1746
+ initialDelaySeconds: 5
1747
+ periodSeconds: 5
1748
+ ---
1749
+ apiVersion: v1
1750
+ kind: Service
1751
+ metadata:
1752
+ name: nestjs-api
1753
+ spec:
1754
+ selector:
1755
+ app: nestjs-api
1756
+ ports:
1757
+ - port: 80
1758
+ targetPort: 3000
1759
+ type: ClusterIP
1760
+ ```
1761
+
1762
+ ### 健康检查
1763
+
1764
+ ```bash
1765
+ npm i @nestjs/terminus
1766
+ ```
1767
+
1768
+ ```typescript
1769
+ @Controller('health')
1770
+ export class HealthController {
1771
+ constructor(
1772
+ private health: HealthCheckService,
1773
+ private db: TypeOrmHealthIndicator,
1774
+ private redis: MicroserviceHealthIndicator,
1775
+ private memory: MemoryHealthIndicator,
1776
+ private disk: DiskHealthIndicator,
1777
+ ) {}
1778
+
1779
+ @Get()
1780
+ check() {
1781
+ return this.health.check([
1782
+ () => this.db.pingCheck('database'),
1783
+ () => this.redis.pingCheck('redis', {
1784
+ transport: Transport.REDIS,
1785
+ options: { host: 'localhost', port: 6379 },
1786
+ }),
1787
+ () => this.memory.checkHeap('memory_heap', 200 * 1024 * 1024), // 200MB
1788
+ () => this.disk.checkStorage('disk', { thresholdPercent: 0.9, path: '/' }),
1789
+ ]);
1790
+ }
1791
+ }
1792
+ ```
1793
+
1794
+ ### Monorepo 结构
1795
+
1796
+ ```bash
1797
+ nest generate app orders-service # 添加子应用
1798
+ nest generate lib shared # 添加共享库
1799
+ ```
1800
+
1801
+ ```
1802
+ project-root/
1803
+ ├── apps/
1804
+ │ ├── api-gateway/ # HTTP 入口
1805
+ │ │ └── src/
1806
+ │ ├── orders-service/ # 订单微服务
1807
+ │ │ └── src/
1808
+ │ └── notifications-service/ # 通知微服务
1809
+ │ └── src/
1810
+ ├── libs/
1811
+ │ ├── shared/ # 共享 DTO / 接口
1812
+ │ │ └── src/
1813
+ │ └── database/ # 共享数据库模块
1814
+ │ └── src/
1815
+ ├── nest-cli.json
1816
+ └── tsconfig.json
1817
+ ```
1818
+
1819
+ ### Serverless 部署
1820
+
1821
+ ```typescript
1822
+ // serverless.ts (AWS Lambda)
1823
+ import { NestFactory } from '@nestjs/core';
1824
+ import { ExpressAdapter } from '@nestjs/platform-express';
1825
+ import serverlessExpress from '@codegenie/serverless-express';
1826
+ import express from 'express';
1827
+
1828
+ let cachedServer: any;
1829
+
1830
+ async function bootstrap() {
1831
+ if (cachedServer) return cachedServer;
1832
+ const expressApp = express();
1833
+ const app = await NestFactory.create(AppModule, new ExpressAdapter(expressApp));
1834
+ app.enableCors();
1835
+ await app.init();
1836
+ cachedServer = serverlessExpress({ app: expressApp });
1837
+ return cachedServer;
1838
+ }
1839
+
1840
+ export const handler = async (event: any, context: any, callback: any) => {
1841
+ const server = await bootstrap();
1842
+ return server(event, context, callback);
1843
+ };
1844
+ ```
1845
+
1846
+ ---
1847
+
1848
+ ## 性能优化
1849
+
1850
+ ### 1. Fastify 适配器
1851
+
1852
+ ```bash
1853
+ npm i @nestjs/platform-fastify
1854
+ ```
1855
+
1856
+ ```typescript
1857
+ import { NestFactory } from '@nestjs/core';
1858
+ import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
1859
+
1860
+ async function bootstrap() {
1861
+ const app = await NestFactory.create<NestFastifyApplication>(
1862
+ AppModule,
1863
+ new FastifyAdapter({ logger: true }),
1864
+ );
1865
+ // 注意:Fastify 需要 listen 绑定 0.0.0.0(Docker/K8s 中必需)
1866
+ await app.listen(3000, '0.0.0.0');
1867
+ }
1868
+ ```
1869
+
1870
+ > **基准参考**: Fastify 适配器在简单 JSON 返回场景下吞吐量约为 Express 的 2x。实际业务中差距缩小,但在高并发场景仍有明显优势。
1871
+
1872
+ ### 2. 压缩
1873
+
1874
+ ```bash
1875
+ npm i @nestjs/platform-express compression
1876
+ ```
1877
+
1878
+ ```typescript
1879
+ import compression from 'compression';
1880
+
1881
+ async function bootstrap() {
1882
+ const app = await NestFactory.create(AppModule);
1883
+ app.use(compression({
1884
+ threshold: 1024, // 仅压缩大于 1KB 的响应
1885
+ level: 6,
1886
+ }));
1887
+ await app.listen(3000);
1888
+ }
1889
+ ```
1890
+
1891
+ ### 3. 懒加载模块
1892
+
1893
+ ```typescript
1894
+ import { LazyModuleLoader } from '@nestjs/core';
1895
+
1896
+ @Injectable()
1897
+ export class ReportService {
1898
+ constructor(private lazyModuleLoader: LazyModuleLoader) {}
1899
+
1900
+ async generateReport() {
1901
+ // 仅在需要时加载重量级模块
1902
+ const { ReportModule } = await import('./report.module');
1903
+ const moduleRef = await this.lazyModuleLoader.load(() => ReportModule);
1904
+ const reportGenerator = moduleRef.get(ReportGenerator);
1905
+ return reportGenerator.generate();
1906
+ }
1907
+ }
1908
+ ```
1909
+
1910
+ ### 4. 集群模式
1911
+
1912
+ ```typescript
1913
+ // main.ts
1914
+ import cluster from 'node:cluster';
1915
+ import os from 'node:os';
1916
+
1917
+ async function bootstrap() {
1918
+ const app = await NestFactory.create(AppModule);
1919
+ await app.listen(3000);
1920
+ }
1921
+
1922
+ if (cluster.isPrimary) {
1923
+ const numCPUs = os.cpus().length;
1924
+ console.log(`Master process ${process.pid}, forking ${numCPUs} workers`);
1925
+ for (let i = 0; i < numCPUs; i++) {
1926
+ cluster.fork();
1927
+ }
1928
+ cluster.on('exit', (worker) => {
1929
+ console.log(`Worker ${worker.process.pid} died, restarting...`);
1930
+ cluster.fork();
1931
+ });
1932
+ } else {
1933
+ bootstrap();
1934
+ }
1935
+ ```
1936
+
1937
+ > **生产建议**: 优先使用 PM2 或 K8s 水平扩展管理多进程,而非手动 cluster。手动 cluster 适合简单部署场景。
1938
+
1939
+ ### 5. 其他优化措施
1940
+
1941
+ ```typescript
1942
+ // 启用 shutdown hooks(优雅关闭)
1943
+ app.enableShutdownHooks();
1944
+
1945
+ // 设置全局前缀
1946
+ app.setGlobalPrefix('api');
1947
+
1948
+ // CORS
1949
+ app.enableCors({
1950
+ origin: ['https://example.com'],
1951
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
1952
+ credentials: true,
1953
+ });
1954
+
1955
+ // Helmet 安全头
1956
+ import helmet from 'helmet';
1957
+ app.use(helmet());
1958
+
1959
+ // 速率限制
1960
+ import { ThrottlerModule, ThrottlerGuard } from '@nestjs/throttler';
1961
+
1962
+ @Module({
1963
+ imports: [
1964
+ ThrottlerModule.forRoot([{
1965
+ ttl: 60000, // 1 分钟
1966
+ limit: 100, // 最多 100 次请求
1967
+ }]),
1968
+ ],
1969
+ providers: [{ provide: APP_GUARD, useClass: ThrottlerGuard }],
1970
+ })
1971
+ export class AppModule {}
1972
+ ```
1973
+
1974
+ ---
1975
+
1976
+ ## 常见陷阱
1977
+
1978
+ ### 1. 循环依赖导致 undefined
1979
+
1980
+ ```typescript
1981
+ // ❌ 错误:A 和 B 互相注入,其中一个会是 undefined
1982
+ @Injectable()
1983
+ export class ServiceA {
1984
+ constructor(private serviceB: ServiceB) {} // 可能是 undefined
1985
+ }
1986
+
1987
+ // ✅ 解决:使用 forwardRef 或提取公共逻辑
1988
+ @Injectable()
1989
+ export class ServiceA {
1990
+ constructor(
1991
+ @Inject(forwardRef(() => ServiceB)) private serviceB: ServiceB,
1992
+ ) {}
1993
+ }
1994
+ ```
1995
+
1996
+ ### 2. 请求作用域的性能问题
1997
+
1998
+ ```typescript
1999
+ // ❌ 不当:对所有服务使用请求作用域
2000
+ @Injectable({ scope: Scope.REQUEST })
2001
+ export class HeavyService {} // 每次请求都创建新实例
2002
+
2003
+ // ✅ 正确:仅在确实需要请求上下文的服务上使用
2004
+ @Injectable()
2005
+ export class HeavyService {
2006
+ doWork(requestContext: RequestContext) {
2007
+ // 通过参数传递请求上下文,保持单例
2008
+ }
2009
+ }
2010
+ ```
2011
+
2012
+ ### 3. 忘记导出 Provider
2013
+
2014
+ ```typescript
2015
+ // ❌ 错误:其他模块无法注入 UsersService
2016
+ @Module({
2017
+ providers: [UsersService],
2018
+ // 缺少 exports
2019
+ })
2020
+ export class UsersModule {}
2021
+
2022
+ // ✅ 正确
2023
+ @Module({
2024
+ providers: [UsersService],
2025
+ exports: [UsersService],
2026
+ })
2027
+ export class UsersModule {}
2028
+ ```
2029
+
2030
+ ### 4. 异步初始化陷阱
2031
+
2032
+ ```typescript
2033
+ // ❌ 错误:同步 forRoot 中使用异步操作
2034
+ @Module({})
2035
+ export class DatabaseModule {
2036
+ static forRoot() {
2037
+ return {
2038
+ module: DatabaseModule,
2039
+ providers: [{
2040
+ provide: 'DB',
2041
+ useValue: connectToDb(), // Promise 未 await!
2042
+ }],
2043
+ };
2044
+ }
2045
+ }
2046
+
2047
+ // ✅ 正确:使用 useFactory + async
2048
+ @Module({})
2049
+ export class DatabaseModule {
2050
+ static forRoot(): DynamicModule {
2051
+ return {
2052
+ module: DatabaseModule,
2053
+ providers: [{
2054
+ provide: 'DB',
2055
+ useFactory: async () => {
2056
+ const conn = await connectToDb();
2057
+ return conn;
2058
+ },
2059
+ }],
2060
+ };
2061
+ }
2062
+ }
2063
+ ```
2064
+
2065
+ ### 5. 测试中未正确清理
2066
+
2067
+ ```typescript
2068
+ // ❌ 错误:测试间共享状态导致随机失败
2069
+ describe('Service', () => {
2070
+ let app: INestApplication;
2071
+ beforeAll(async () => { app = /* ... */ });
2072
+ // 测试完没有关闭
2073
+
2074
+ // ✅ 正确:每次清理
2075
+ afterAll(async () => {
2076
+ await app.close();
2077
+ });
2078
+ });
2079
+ ```
2080
+
2081
+ ### 6. ValidationPipe 未配置 whitelist
2082
+
2083
+ ```typescript
2084
+ // ❌ 危险:客户端可注入任意属性
2085
+ app.useGlobalPipes(new ValidationPipe());
2086
+ // POST { name: "Alice", isAdmin: true } -> isAdmin 会被传入 DTO
2087
+
2088
+ // ✅ 安全:只保留 DTO 中定义的属性
2089
+ app.useGlobalPipes(new ValidationPipe({
2090
+ whitelist: true,
2091
+ forbidNonWhitelisted: true,
2092
+ }));
2093
+ ```
2094
+
2095
+ ### 7. 生产环境 synchronize: true
2096
+
2097
+ ```typescript
2098
+ // ❌ 灾难性:自动同步会删除数据列
2099
+ TypeOrmModule.forRoot({
2100
+ synchronize: true, // 绝对不能在生产环境开启
2101
+ });
2102
+
2103
+ // ✅ 正确:使用迁移管理数据库变更
2104
+ TypeOrmModule.forRoot({
2105
+ synchronize: false,
2106
+ migrations: ['dist/migrations/*.js'],
2107
+ migrationsRun: true,
2108
+ });
2109
+ ```
2110
+
2111
+ ---
2112
+
2113
+ ## 最佳实践
2114
+
2115
+ 1. **模块边界清晰**: 每个功能域一个模块,通过 exports 控制可见性
2116
+ 2. **DTO 验证一切输入**: 使用 class-validator + ValidationPipe(whitelist: true)
2117
+ 3. **依赖注入优于直接导入**: 提高可测试性,便于替换实现
2118
+ 4. **使用 ConfigModule 管理配置**: 不要直接读取 process.env
2119
+ 5. **全局异常过滤器**: 统一错误响应格式
2120
+ 6. **全局拦截器**: 响应包装、日志、超时控制
2121
+ 7. **接口而非实现**: 使用自定义 token 注入,便于切换实现
2122
+ 8. **健康检查端点**: 必须暴露 /health 用于 K8s 探针
2123
+ 9. **优雅关闭**: 启用 shutdownHooks,处理 SIGTERM
2124
+ 10. **日志结构化**: 使用 Pino 或 Winston,输出 JSON 格式日志
2125
+
2126
+ ---
2127
+
2128
+ ## 参考资料
2129
+
2130
+ - [NestJS 官方文档](https://docs.nestjs.com/)
2131
+ - [NestJS GitHub](https://github.com/nestjs/nest)
2132
+ - [Awesome NestJS](https://github.com/nestjsx/awesome-nestjs)
2133
+ - [NestJS 官方示例集合](https://github.com/nestjs/nest/tree/master/sample)
2134
+
2135
+ ---
2136
+
2137
+ ## Agent Checklist
2138
+
2139
+ - [ ] 项目使用 `nest new` 或手动创建时,确认 `reflect-metadata` 和 `rxjs` 已安装
2140
+ - [ ] 模块结构遵循功能域划分,每个域独立模块 + 控制器 + 服务
2141
+ - [ ] 全局 ValidationPipe 配置 whitelist + forbidNonWhitelisted + transform
2142
+ - [ ] 全局异常过滤器统一错误响应格式
2143
+ - [ ] 数据库 synchronize 在生产环境为 false,使用迁移管理
2144
+ - [ ] TypeORM 事务使用 QueryRunner 或 DataSource.transaction()
2145
+ - [ ] Prisma 使用 $transaction 保证原子性
2146
+ - [ ] JWT 认证使用 Passport + @nestjs/jwt,token 有过期时间
2147
+ - [ ] RBAC 守卫与 @Roles() 装饰器配合使用
2148
+ - [ ] WebSocket Gateway 配置认证中间件
2149
+ - [ ] 微服务客户端使用 ClientProxy 通信,区分 send(请求-响应)和 emit(事件)
2150
+ - [ ] GraphQL 使用 DataLoader 解决 N+1 查询问题
2151
+ - [ ] 队列任务配置重试策略和失败保留策略
2152
+ - [ ] 缓存使用 Redis,写操作后主动失效相关缓存
2153
+ - [ ] Docker 使用多阶段构建,非 root 用户运行
2154
+ - [ ] K8s 配置 liveness/readiness 探针指向 /health
2155
+ - [ ] 启用 shutdownHooks 实现优雅关闭
2156
+ - [ ] 启用 Helmet + CORS + ThrottlerGuard 安全措施
2157
+ - [ ] 单元测试使用 Testing 模块 Mock 依赖
2158
+ - [ ] E2E 测试使用 overrideProvider/overrideGuard 隔离外部依赖
2159
+ - [ ] 无循环依赖;若无法避免,使用 forwardRef 并注释原因
2160
+ - [ ] 生产环境使用 Fastify 适配器或 PM2/K8s 水平扩展
2161
+ - [ ] ConfigModule 集中管理所有环境变量,不直接使用 process.env
2162
+
2163
+ ---
2164
+
2165
+ **文档版本**: v1.0
2166
+ **最后更新**: 2026-03-28
2167
+ **质量评分**: 92/100