NestJS GraphQL 结构
NestJS GraphQL(代码优先)应用程序中每个文件应放置的位置,以及每个文件如何工作。本技能是一个放置与结构指南:它回答“这个文件放在哪个目录下?”、“这个文件负责什么?”以及“模块如何连接以解析字段和关系?”。它涵盖基础结构映射以及模块、服务、解析器(查询、变更、订阅、字段)、输入与参数、分页、实体(共享类型的 Mongoose Schema 最佳实践)、仅仓库模型注入、模型/映射器、仓库、Mongoose 鉴别器、派生字段、提供者、加载器、事件、后台任务、认证、异常、自定义标量、配置、通用构建块、基础设施设置以及命名/测试/代码风格约定的逐文件规则。
它特意与 nestjs-best-practices 技能分开。该技能涵盖框架行为(依赖注入深度、安全性、性能、错误处理、微服务、DevOps);本技能涵盖结构和模块组成。如果两者重叠(特性模块、循环依赖),本技能通过放置角度审视,并交叉引用其他技能以获取行为深度。
本技能涵盖结构规则(文件存放位置)和模块解析规则(模块在运行时如何连接——例如循环依赖解析)。模块解析规则位于第 2 节和第 3 节。
适用时机
在以下情况参考本指南:
- 确定新文件在 NestJS GraphQL 代码库中的归属
- 设计或审查特性优先的目录布局
- 搭建新特性模块及其文件
- 决定如何对多态文档建模(Mongoose 鉴别器)并自动发布其 GraphQL 类型
- 决定 Mongoose 模型可以注入何处——并将数据库访问保留在仓库后面
- 决定某个值是否属于数据库,还是应在读取时派生
- 解决模块如何解析位于另一个模块中的字段或关系
- 解决模块之间的连接问题(循环依赖、缺少导出)
按优先级分类的规则
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 应用程序结构 | 关键 | struct- |
| 2 | 模块与启动 | 关键 | module- |
| 3 | 关系与跨模块 | 关键 | relations- |
| 4 | 服务 | 高 | service- |
| 5 | GraphQL 解析器 | 高 | resolver- |
| 6 | GraphQL 类型与输入 | 高 | type- |
| 7 | 数据访问 | 中高 | data- |
| 8 | 配置、通用与基础设施 | 中 | infra- |
| 9 | 约定与测试 | 中 | conventions- |
快速参考
1. 应用程序结构(关键)
struct-auth-feature- 将认证保留在其自己的特性模块中struct-canonical-layout- 规范的应用程序结构struct-feature-decomposition- 当特性增长时将其拆分为子模块struct-file-placement-table- 文件放置表struct-module-kinds- 区分领域特性与应用级模块struct-schema-artifact- 定位并策略化生成的 Schema 产物
2. 模块与启动(关键)
module-bootstrap- 保持 main.ts 和 app.module.ts 精简module-export-policy- 仅导出特性的公共 API(其服务)module-feature-module- 特性模块文件
3. 关系与跨模块(关键)
relations-avoid-circular- 解决循环模块依赖relations-dataloader- 使用按请求的 DataLoader 批量处理关系relations-events- 通过事件解耦模块relations-field-resolvers- 使用 @ResolveField 解析关系relations-owning-module- 将关系字段放在拥有其数据的模块中
4. 服务(高)
service-background-jobs- 将队列处理器和计划任务保留在特性内部service-external-providers- 将第三方客户端保留在 providers/ 中service-interfaces-tokens- 在 interfaces/ 中声明服务契约和注入令牌service-single-responsibility- 每个模块有多个专注的服务service-small-focused-methods- 保持服务方法小巧且专注
5. GraphQL 解析器(高)
resolver-computed-fields- 在类型上声明字段;在解析器中解析计算字段resolver-organization- 按角色将解析器拆分到 resolvers/ 中resolver-per-type- 每个具有字段解析器的类型一个解析器文件resolver-subscriptions- 将订阅解析器放在 resolvers/ 中,PubSub 放在 infra/ 中
6. GraphQL 类型与输入(高)
type-args- 在 dto/ 中定义 @Args 类type-inputs- 在 dto/ 中定义 GraphQL 输入type-pagination- 使用共享的页面类型对列表查询进行分页type-polymorphic-discriminators- 将鉴别文档作为接口或联合发布type-unions-interfaces- 将联合和接口类型放在模块的类型文件中
7. 数据访问(中高)
data-derived-fields- 计算派生字段;不存储它们data-discriminators- 使用鉴别器对多态子类型建模data-entity-mongodb- 将 MongoDB 实体放在 entities/ 中data-model-injection- 仅在仓库中注入模型data-models-mappers- 当 API 与存储不同时拆分 models/ 和 mappers/data-mongoose-schema- 共享类型的 Mongoose Schema 最佳实践data-repository- 将数据访问保留在 repositories/ 中
8. 配置、通用与基础设施(中)
infra-common-types- 将共享类型放在 common/types/ 中infra-common- 将共享构建块放在 common/ 中infra-config- 将带类型的配置放在 config/ 中infra-custom-scalars- 在 common/scalars/ 中实现自定义标量infra-database- 将数据库设置和迁移放在 infra/database/ 中infra-directives- 将 Schema 指令放在 common/directives/ 中infra-exceptions- 将异常放在 exceptions/ 中infra-graphql- 将 GraphQL 设置放在 infra/graphql/ 中infra-seeds- 将种子脚本放在 infra/database/seeds/ 中infra-shared-module- 使用 SharedModule 处理横切关注点
9. 约定与测试(中)
conventions-barrels-aliases- 有目的地使用桶文件和路径别名conventions-cli-generator- 使用 Nest CLI 生成器,然后调整conventions-constants-enums- 将常量和枚举保留在类文件之外conventions-module-boundaries- 通过 lint 强制模块边界conventions-naming- 文件和类命名约定conventions-test-fixtures- 将测试夹具、工厂和助手放在 test/ 中conventions-testing- 测试文件放置
如何使用
从基础结构规则开始,然后阅读正在处理的特定文件类型的规则。规则文件位于 rules/ 下:
rules/struct-canonical-layout.md
rules/_sections.md
每个规则文件包含:
- 目的和放置位置(文件存放位置及其命名方式)
- 责任与反责任
- 一个错误示例及其说明
- 一个正确示例及其说明
完整编译文档
有关所有规则展开到单个文档的完整指南,请参阅 AGENTS.md。