GraphQL Schema 设计 + Resolver 实现
从业务领域模型设计 GraphQL Schema,生成类型安全的 Resolver、DataLoader、指令、联合类型
提示词
你是 GraphQL 架构师。任务:设计生产级 GraphQL Schema 与 Resolver 实现。
约束:
- Schema 设计原则:
- 以业务领域为中心,非数据库映射
- 命名:PascalCase 类型,camelCase 字段
- 连接规范:Relay Cursor Connections Specification
- 接口/联合类型建模多态
- @deprecated 标记废弃字段,说明迁移路径
- Resolver 实现:
- DataLoader 解决 N+1
- 权限指令:@auth(requires: ADMIN)
- 错误扩展:extensions.code
- 订阅:asyncIterator + PubSub
- 代码生成:GraphQL Codegen -> TypeScript 类型
- 输出:schema.graphql + resolvers.ts + dataloaders.ts + codegen.yml
输出格式:
schema.graphql:
// resolvers.ts
codegen.yml:
少样本示例
展示 Relay Connection、接口、订阅、DataLoader、权限指令
输入
业务:内容管理系统。实体:Article、Author、Category、Comment。需求:文章列表(分页/筛选)、文章详情、作者主页、评论树、实时新评论订阅。
输出
schema.graphql 片段:
type Query {
articles(filter: ArticleFilter, after: String, first: Int): ArticleConnection!
article(id: ID!): Article
author(id: ID!): Author
}
type Mutation {
createArticle(input: CreateArticleInput!): Article! @auth(requires: AUTHOR)
addComment(input: AddCommentInput!): Comment! @auth(requires: USER)
}
type Subscription {
commentAdded(articleId: ID!): Comment! @auth(requires: USER)
}
interface Node { id: ID! }
type Article implements Node {
id: ID!
title: String!
content: String!
author: Author!
category: Category
comments(after: String, first: Int): CommentConnection!
createdAt: DateTime!
}
type Author implements Node {
id: ID!
name: String!
avatar: String
articles(after: String, first: Int): ArticleConnection!
}
... Connection types, Input types, Scalars:
resolvers.ts 片段:
const resolvers = {
Query: {
articles: async (_, { filter, first, after }, { dataLoaders }) => {
const edges = await dataLoaders.articles.load({ filter, first, after });
return connectionFromArray(edges, { first, after });
},
},
Article: {
author: (article, , { dataLoaders }) => dataLoaders.author.load(article.authorId),
comments: (article, { first, after }, { dataLoaders }) =>
dataLoaders.commentsByArticle.load({ articleId: article.id, first, after }),
},
Subscription: {
commentAdded: {
subscribe: (, { articleId }, { pubsub }) => pubsub.asyncIterator(COMMENT_${articleId}),
},
},
};