博客

🎉 Gato GraphQL v0.7 发布 — 新增 mutation 和 nested mutation 支持!

Leonardo Losoviz
作者:Leonardo Losoviz ·

Gato GraphQL 的 0.7 版本已正式发布,支持 mutation 和 nested mutation! 🎉

Mutation 真是太棒了!

以下是新增功能的介绍。

1. Mutations! 🚀

GraphQL mutations 允许通过 query 修改数据(即执行副作用操作)。

Mutation 是 Gato GraphQL 此前缺失的重要功能。现在它已被添加,我可以说这个 GraphQL 服务器已基本功能完整(只剩 subscriptions 尚未实现,我已经在考虑如何添加了)。

交互式 schema 中的 Mutation root

让我们来看一个添加评论的示例。不过首先,我们需要执行另一个 mutation 来登录,这样才能添加评论。请点击下方 GraphiQL 客户端中的「Run」按钮,使用预先创建的测试用户执行 mutation 字段 loginUser

mutation LogUserIn {
  loginUser(
    by: { credentials: { usernameOrEmail: "test", password: "pass" } }
  ) {
    id
    name
  }
}

现在,让我们添加一些评论。点击下方的 Run 按钮,通过执行 mutation 字段 addCommentToCustomPost 向某篇文章添加评论(你也可以编辑评论内容):

mutation AddComment {
  addCommentToCustomPost(
    input: { customPostID: 1459, comment: "Adding a comment: bla bla bla" }
  ) {
    id
    content
    date
  }
}

在此首个版本中,插件包含以下 mutation:

createPost
updatePost
setFeaturedImageforCustomPost
removeFeaturedImageforCustomPost
addCommentToCustomPost
replyComment
loginUser
logoutUser

2. Nested Mutations! 🚀🚀

Nested mutations 是指在 GraphQL 的 root type 以外的类型上执行 mutation 的能力。

这一特性已被提议纳入 GraphQL 规范,但尚未获得批准(也可能永远不会获批)。因此,Gato GraphQL 通过 Nested Mutations 模块将其作为可选功能提供支持。

插件支持以下两种行为:

  1. 标准 GraphQL 行为(即将 mutation 字段添加到 root type),默认启用
  2. Nested mutations,作为可选功能启用

例如,上述 query 也可以用以下方式执行:先通过 Root.post 获取文章,然后通过 Post.addComment 添加评论:

mutation AddComment {
  post(by: { id: 1459 }) {
    addComment(
      input: {
        comment: "Notice how field `addCommentToCustomPost` under the `Root` type is renamed as `addComment` under the `Post` type? The schema got neater!"
      }
    ) {
      id
      content
      date
    }
  }
}

Mutation 也可以对另一个 mutation 的结果执行数据修改。在下面的 query 中,我们首先通过 Root.post 获取文章,然后对其执行 mutation Post.addComment 并获取创建的评论对象,最后对该评论执行 mutation Comment.reply

mutation AddCommentAndResponse {
  post(by: { id: 1459 }) {
    id
    title
    addComment(input: { comment: "Isn't this awesome?" }) {
      id
      date
      content
      reply(input: { comment: "I think so!" }) {
        id
        date
        content
      }
    }
  }
}

这真的非常实用! 😍 (在单个 query 中实现相同行为的替代方式是使用 @export 指令……我会在后续的博客文章中对两者进行比较)。


在此首个版本中,插件包含以下 mutation:

CustomPost.update
CustomPost.setFeaturedImage
CustomPost.removeFeaturedImage
CustomPost.addComment
Comment.reply

标准还是 nested?或者两者都要?

你可能有一个 GraphQL API,既供自己的应用程序使用,也向客户端公开。你可能希望为自己的应用程序启用 nested mutations,但由于这是非标准功能,不希望为客户端启用。

好消息是:这完全可以实现。

我在 Schema Configuration 中添加了「Mutation Scheme」部分,用于为 Custom EndpointsPersisted Queries 自定义 schema:

Schema configuration 中的 Mutation scheme

这样,你可以在所有地方禁用 nested mutations,但仅为自己应用程序专用的特定 custom endpoint 启用它。 💪

从 root type 中移除冗余字段

使用 nested mutations 时,mutation 字段可能会被添加到 schema 中两次:

  • 一次在 root type 下
  • 一次在特定类型下

例如,以下字段可以视为彼此的「重复」:

  • Root.updatePost
  • Post.update

Gato GraphQL 允许你保留两者,或移除 root type 中那些冗余的字段。

以下 3 种 schema:

  1. 标准行为:
    使用 QueryRoot 类型处理 query,使用 MutationRoot 类型处理 mutation
  2. 保留重复 mutation 字段的 nested mutations:
    单一的 Root 类型同时处理 query 和 mutation,该类型中的冗余 mutation 字段被保留
  3. 从 root type 移除冗余 mutation 字段的 nested mutations:
    与上述相同,但从 Root 类型中移除所有冗余的 mutation 字段

✱ 顺带一提1:这 3 种 schema 都使用同一个端点,通过将 URL 参数 ?mutation_scheme 改为 standardnestedlean_nested 来切换。这得益于 GraphQL 服务器遵循了 code-first 方式。 🤟

✱ 顺带一提2:这些选项可以在 Schema configuration(如上图所示)的「Mutation Scheme」部分中选择,因此你也可以决定对各个 custom endpoints 和 persisted queries 应用何种行为。 👏


现在是时候开始为 v0.8 做准备了! 🙏


订阅我们的新闻通讯

及时了解 Gato GraphQL 的所有更新。