Mutations no GraphQL: sintaxe, variáveis e input types | We.Inc
Escreva mutations GraphQL que criam, atualizam e apagam dados: sintaxe da operação, $variables, input object types, o que retornar e como ficam erros e sucesso parcial.
Uma mutation GraphQL é a operação que você envia para alterar dados. Ela começa com a palavra-chave mutation, chama um campo do tipo Mutation do schema, passa argumentos, geralmente um input object guardado em uma $variable, e seleciona quais campos do resultado devolver. Os campos de mutation de nível superior rodam um depois do outro, nunca em paralelo.
A sintaxe da mutation em partes
Parte
Exemplo
O que faz
Palavra-chave e nome
mutation AddTask
Marca a operação como escrita e dá um nome a ela para os logs
Definição de variáveis
($input: TaskInput!)
Declara valores tipados enviados à parte como JSON
Campo raiz
addTask(input: $input)
Um campo definido no tipo Mutation
Selection set
{ id title done }
Campos do resultado a devolver
JSON de variáveis
{"input": {...}}
Os valores de fato, mantidos fora da string da query
Use o gerador abaixo para ver uma mutation completa para uma pequena lista de tarefas: a operação, o JSON de variáveis que o seu código enviaria junto e uma resposta típica. Digite o título de uma tarefa e veja as variáveis se atualizarem, para copiar uma requisição pronta para rodar contra um schema compatível.
Escolha criar, atualizar ou apagar.
Digite um título para a tarefa; o JSON de variáveis se atualiza enquanto você digita.
Copie a mutation e as variáveis e envie como as chaves query e variables de um único POST.
Compare a resposta do seu servidor com a resposta de exemplo mostrada abaixo deles.
Envie valores por variáveis em vez de colá-los na string da query. Isso evita bugs de escape e permite que os servidores façam cache do documento já processado.
Retorne o objeto alterado, incluindo o id, para que os caches do cliente atualizem a tela sem uma segunda requisição.
Dê nome a toda operação. Mutations nomeadas são muito mais fáceis de achar em logs do servidor e relatórios de erro.
Trate vários campos raiz em uma mutation como etapas separadas, não como uma transação: um campo anterior continua feito quando um posterior falha.
Perguntas frequentes
Qual é a diferença entre uma query e uma mutation?
As duas usam a mesma sintaxe e as duas podem retornar dados. Por convenção, queries só leem e mutations escrevem. A regra de execução também muda: campos de query podem ser resolvidos em paralelo, enquanto campos de mutation de nível superior rodam em série.
Por que usar um input type em vez de argumentos simples?
Um input object agrupa valores relacionados em um único argumento tipado, então a assinatura da mutation fica curta e você pode adicionar campos opcionais depois sem mudar cada chamada.
Dá para enviar uma mutation com uma requisição GET?
Não. As orientações de GraphQL over HTTP permitem que servidores aceitem GET só para operações de query. Mutations vão como POST, o que também mantém as escritas longe dos caches do navegador e de CDN.
Uma mutation com vários campos é atômica?
Não. O graphql.org observa que a execução em série não é uma transação de banco de dados. Se o segundo campo falhar, a alteração do primeiro permanece, e a resposta traz dados de um e um erro do outro.
O que uma mutation de exclusão deve retornar?
A spec deixa isso com você, mas o campo ainda precisa de um tipo de saída. Escolhas comuns são o id do objeto apagado, o próprio objeto removido ou um tipo de payload com o id e uma flag de sucesso.
Anatomia de uma mutation
No servidor, o schema declara um tipo Mutation cujos campos são as escritas que os clientes podem chamar, cada um com argumentos e um tipo de retorno. No cliente, a operação cita um ou mais desses campos, passa argumentos e escolhe os campos do resultado que quer de volta.
Se o campo retorna um tipo de objeto, um selection set é obrigatório, como em uma query. Pedir o novo id e os campos que a tela mostra permite que o cliente atualize a visualização direto a partir da resposta.
Variáveis e input objects
As variáveis são declaradas depois do nome da operação com um cifrão e um tipo, como $input: TaskInput!. O ponto de exclamação torna a variável obrigatória. Os valores viajam em um objeto variables separado no corpo da requisição.
Um input object type é declarado com a palavra-chave input em vez de type. Os campos dele só podem ser escalares, enums, listas ou outros input types, o que mantém o formato do que os clientes enviam fácil de validar.
Erros em uma escrita
Se o documento é inválido, por exemplo um campo escrito errado ou uma variável obrigatória faltando, o servidor responde com errors e sem data, e nada é gravado.
Se a escrita em si falha durante a execução, o campo volta como null e uma entrada em errors traz uma mensagem e um path. Muitos schemas também retornam problemas esperados, como um título longo demais, como campos de um tipo de payload, para que o cliente possa mostrá-los ao lado do formulário.
O schema por trás dos exemplos
Tipo Mutation e input types
Input types usam a palavra-chave input. TaskPatch não tem campos obrigatórios, então uma atualização pode enviar só o que mudou.
Enviando a partir do JavaScript
Faça POST da mutation com fetch
O documento e as variáveis viajam como duas chaves de um único corpo JSON. Verifique errors mesmo quando o status é 200.
Duas escritas em uma operação
Aliases permitem rodar o mesmo campo duas vezes. O segundo só roda depois que o primeiro termina, mas uma falha nele não desfaz o primeiro.
Criar
O input type agrupa os campos da nova tarefa. O selection set pede o id que o servidor atribuiu.
Atualizar
O id diz qual tarefa alterar e o input traz só os campos que mudam.
Apagar
Não sobra nada para selecionar em uma tarefa removida, então este schema retorna o id apagado como um escalar ID simples.
Gerador de mutations
Escolha uma mutation
Título da tarefa
Mutation
Variáveis (JSON)
Resposta de exemplo
Copiar mutation
Copiar variáveis
Apagar precisa só do id, então o título não é enviado.