Gerenciando payloads de mutations
Os campos de mutation podem ser configurados para retornar um destes 2 tipos de entidade distintos:
- Um tipo de objeto payload
- Diretamente a entidade modificada
Tipo de objeto payload
Um tipo de objeto payload contém todos os dados relacionados à mutation:
- O status da mutation (sucesso ou falha)
- Os erros (se houver) usando tipos GraphQL distintos, ou
- A entidade modificada com sucesso
Por exemplo, a mutation updatePost retorna um objeto do tipo PostUpdateMutationPayload, e ainda precisamos consultar seu campo post para recuperar a entidade post atualizada:
mutation UpdatePost {
updatePost(input: {
id: 1724,
title: "New title",
status: publish
}) {
# This is the status of the mutation: SUCCESS or FAILURE
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
id
title
# This is the status of the post: publish, pending, trash, etc
status
}
}
}O objeto payload nos permite representar melhor os erros, tendo inclusive um tipo GraphQL único para cada tipo de erro. Isso nos permite apresentar reações diferentes para erros diferentes na aplicação, melhorando assim a experiência do usuário.
No exemplo acima, se a operação foi bem-sucedida, receberemos:
{
"data": {
"updatePost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1724,
"title": "Some title",
"status": "publish"
}
}
}
}Se o usuário não estiver autenticado, receberemos:
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "UserIsNotLoggedInErrorPayload",
"message": "You must be logged in to create or update custom posts"
}
],
"post": null
}
}
}Se o usuário não tiver permissão para editar posts, receberemos:
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
"message": "Your user doesn't have permission for editing custom posts."
}
],
"post": null
}
}
}Neste modo, o schema GraphQL conterá muitos tipos adicionais MutationPayload, MutationErrorPayloadUnion e ErrorPayload, portanto terá um tamanho maior:

Consultar os objetos payload das mutations
Cada mutation no schema possui um campo correspondente para consultar seus objetos payload criados recentemente, com o nome {mutationName}MutationPayloadObjects.
Esses campos incluem:
addCommentToCustomPostMutationPayloadObjects(paraaddCommentToCustomPost)createCustomPostMutationPayloadObjects(paracreateCustomPost)createMediaItemMutationPayloadObjects(paracreateMediaItem)createPageMutationPayloadObjects(paracreatePage)createPostMutationPayloadObjects(paracreatePost)removeFeaturedImageFromCustomPostMutationPayloadObjects(pararemoveFeaturedImageFromCustomPost)replyCommentMutationPayloadObjects(parareplyComment)setCategoriesOnPostMutationPayloadObjects(parasetCategoriesOnPost)setFeaturedImageOnCustomPostMutationPayloadObjects(parasetFeaturedImageOnCustomPost)setTagsOnPostMutationPayloadObjects(parasetTagsOnPost)updateCustomPostMutationPayloadObjects(paraupdateCustomPost)updatePageMutationPayloadObjects(paraupdatePage)updatePostMutationPayloadObjects(paraupdatePost)
Esses campos nos permitem recuperar os resultados de mutations executadas com @applyField durante a iteração nos itens de um array.
Por exemplo, a seguinte query duplica posts em massa:
query GetPostsAndExportData
{
postsToDuplicate: posts {
title
rawContent
excerpt
# Already create (and export) the inputs for the mutation
postInput: _echo(value: {
title: $__title
contentAs: {
html: $__rawContent
},
excerpt: $__excerpt
})
@export(as: "postInput", type: LIST)
@remove
}
}
mutation CreatePosts
@depends(on: "GetPostsAndExportData")
{
createdPostMutationPayloadObjectIDs: _echo(value: $postInput)
@underEachArrayItem(
passValueOnwardsAs: "input"
)
@applyField(
name: "createPost"
arguments: {
input: $input
},
setResultInResponse: true
)
@export(as: "createdPostMutationPayloadObjectIDs")
}
query DuplicatePosts
@depends(on: "CreatePosts")
{
createdPostMutationObjectPayloads: createPostMutationPayloadObjects(input: {
ids: $createdPostMutationPayloadObjectIDs
}) {
status
errors {
__typename
...on ErrorPayload {
message
}
}
post {
id
title
rawContent
excerpt
}
}
}Por padrão, esses campos não são adicionados ao schema GraphQL. Para isso, devemos selecionar a opção "Use payload types for mutations, and add fields to query those payload objects".
Entidade modificada
A mutation retornará diretamente a entidade modificada em caso de sucesso, ou null em caso de falha, e qualquer mensagem de erro será exibida na entrada de nível superior errors da resposta JSON.
Por exemplo, a mutation updatePost retornará o objeto do tipo Post:
mutation UpdatePost {
updatePost(input: {
id: 1724,
title: "New title",
status: publish
}) {
id
title
status
}
}Se a operação foi bem-sucedida, receberemos:
{
"data": {
"updatePost": {
"id": 1724,
"title": "Some title",
"status": "publish"
}
}
}Em caso de erros, eles aparecerão na entrada errors da resposta. Por exemplo, se o usuário não estiver autenticado, receberemos:
{
"errors": [
{
"message": "You must be logged in to create or update custom posts'",
"locations": [
{
"line": 2,
"column": 3
}
]
}
],
"data": {
"updatePost": null
}
}Devemos notar que, como resultado, a entrada de nível superior errors conterá não apenas erros de sintaxe, de validação de schema e de lógica (ex.: não passar o nome de um argumento de campo, solicitar um campo inexistente, ou chamar _sendHTTPRequest enquanto a rede está fora, respectivamente), mas também erros de "validação de conteúdo" (ex.: "você não tem autorização para modificar este post").
Como não há tipos adicionais inseridos, o schema GraphQL terá uma aparência mais enxuta:

Gerenciando o tipo de objeto payload para mutations
Vejamos como lidar com a primeira opção, o tipo de objeto payload.
As mutations no schema retornam algum objeto payload, que fornece qualquer erro resultante da mutation, ou o objeto modificado em caso de sucesso (essas 2 propriedades são muito provavelmente exclusivas: ou errors ou object terá um valor, e o outro será null).
Os erros são fornecidos por meio de algum tipo "ErrorPayloadUnion", contendo todos os possíveis erros para aquela mutation. Cada erro possível é algum tipo "ErrorPayload" que implementa a interface ErrorPayload.
Por exemplo, a operação updatePost retorna um PostUpdateMutationPayload, que contém os seguintes campos:
status: se a operação foi bem-sucedida ou não, com o valorSUCCESSouFAILUREpostepostID: o objeto post atualizado e seu ID, se a atualização foi bem-sucedidaerrors: uma lista deCustomPostUpdateMutationErrorPayloadUnion, se a atualização falhou.
O tipo union CustomPostUpdateMutationErrorPayloadUnion contém a lista de todos os possíveis erros que podem ocorrer ao modificar um custom post:
CustomPostDoesNotExistErrorPayloadGenericErrorPayloadLoggedInUserHasNoEditingCustomPostCapabilityErrorPayloadLoggedInUserHasNoPermissionToEditCustomPostErrorPayloadLoggedInUserHasNoPublishingCustomPostCapabilityErrorPayloadUserIsNotLoggedInErrorPayload
O tipo de erro GenericErrorPayload está contido em todos os tipos "ErrorPayloadUnion". Ele é usado sempre que a razão específica do erro não pode ser identificada, como quando wp_update_post simplesmente produz WP_Error. Esse tipo fornece dois campos adicionais: code e data.
Então, para executar a mutation updatePost, podemos executar:
mutation UpdatePost(
$postId: ID!
$title: String!
) {
updatePost(
input: {
id: $postId,
title: $title,
}
) {
status
errors {
__typename
...on ErrorPayload {
message
}
...on GenericErrorPayload {
code
}
}
post {
id
title
}
}
}Se a operação foi bem-sucedida, receberemos:
{
"data": {
"updatePost": {
"status": "SUCCESS",
"errors": null,
"post": {
"id": 1724,
"title": "This incredible title"
}
}
}
}Se o usuário não estiver autenticado, receberemos:
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "UserIsNotLoggedInErrorPayload",
"message": "You must be logged in to create or update custom posts"
}
],
"post": null
}
}
}Se o usuário não tiver permissão para editar posts, receberemos:
{
"data": {
"updatePost": {
"status": "FAILURE",
"errors": [
{
"__typename": "LoggedInUserHasNoEditingCustomPostCapabilityErrorPayload",
"message": "Your user doesn't have permission for editing custom posts."
}
],
"post": null
}
}
}