Autenticar com o GraphQL
Para comunicar-se com o servidor GraphQL, você precisará de um token do OAuth com os escopos corretos.
Siga as etapas em "Criando um token de acesso pessoal" para criar um token. Os escopos de que você precisa dependem do tipo de dados que você está tentando solicitar. Por exemplo, selecione os escopos Usuário para solicitar os dados do usuário. Se você precisar de acesso às informações do repositório, selecione os escopos apropriados do repositório.
Recomendam-se os escopos a seguir:
usuário
public_repo
repo
repo_deployment
repo:status
read:repo_hook
read:org
read:public_key
read:gpg_key
A API envia uma notificação se um recurso precisar de um escopo específico.
O ponto final do GraphQL
A API REST tem inúmeros pontos finais; a API do GraphQL tem um único ponto final:
http(s)://[hostname]/api/graphql
O ponto de final permanece constante, independentemente da operação que você realizar.
Comunicação com o GraphQL
Como as operações do GraphQL consistem em várias linhas do JSON, o GitHub recomenda o uso do Explorer para fazer chamadas do GraphQL. Você também pode usar a cURL ou qualquer outra biblioteca com linguagem HTTP.
Na REST, verbos HTTP determinam a operação realizada. No GraphQL, você fornecerá um texto codificado pelo JSON, se você estiver realizando uma consulta ou uma mutação. Portanto, o verbo HTTP será POST
. A exceção é uma consulta de introspecção, que são um GET
simples para o ponto final. Para obter mais informações sobre GraphQL em comparação com a REST, consulte "Migrando da REST para o GraphQL".
Para consultar o GraphQL usando a cURL, faça uma solicitação de POST
com uma carga do JSON. A carga deve conter uma string denominada consulta
:
curl -H "Authorization: bearer token" -X POST -d " \
{ \
\"query\": \"query { viewer { login }}\" \
} \
" http(s)://[hostname]/api/graphql
Observação: O valor da string de "consulta"
deve pular caracteres de uma linha nova. Caso contrário, o esquema não fará a análise correta. Para o texto do POST
, use aspas duplas exteriores e aspas duplas para aspas internas.
Sobre consultas e operações de mutação
Os dois tipos de operações permitidas na API do GraphQL do GitHub são consultas e mutações. Comparando o GraphQL com a REST, as consultas funcionam como solicitações do GET
, enquanto as mutações funcionam como POST
/PATCH
/EXCLUIR
. O nome da mutação determina qual modificação é executada.
Para obter informações sobre limite de taxas, consulte "limitações de recursos do GraphQL".
As consultas e mutações compartilham formas semelhantes, com algumas diferenças importantes.
Sobre as consultas
As consultas do GraphQL retornam apenas os dados especificados. Para gerar uma consulta, você deve especificar os campos dentro dos campos (também conhecidos como subcampos aninhados) até que retorne apenas escalares.
As consultas estão estruturadas da seguinte forma:
query { JSON objects to return }
Para obter um exemplo real, consulte "Consulta de exemplo."
Sobre as mutações
Para formar uma mutação, você deve especificar três coisas:
- Nome da mutação. O tipo de modificação que você deseja realizar.
- Objeto de entrada. Os dados que você deseja enviar para o servidor, compostos de campos de entrada. Passe-o como um argumento para o nome de mutação.
- Objeto da carga. Os dados que você deseja retornar do servidor, compostos de campos de retorno. Passe-o como o texto do nome da mutação.
As mutações são estruturadas da seguinte forma:
mutation { mutationName(input: {MutationNameInput!}) { MutationNamePayload }
Neste exemplo, o objeto de entrada é MutationNameInput
e o objeto de carga é MutationNamePayload
.
Na referência mutações, os campos de entrada listados são o que você passa como o objeto de entrada. Os campos de retorno listados são o que você passa como objeto de carga.
Para obter um exemplo real, consulte "Exemplo de mutação."
Trabalhar com variáveis
As Variáveis podem tornar as consultas mais dinâmicas e poderosas, além de reduzir a complexidade ao passar objetos de entrada de mutação.
Observação: se você estiver usando o Explorador, certifique-se de inserir as variáveis no painel separado das Variáveis de consulta, e não inclua a palavra variáveis
antes do objeto do JSON.
Aqui está um exemplo de consulta com uma única variável:
query($number_of_repos:Int!) query($number_of_repos:Int!) {
viewer {
name
repositories(last: $number_of_repos) {
nodes {
name
}
}
}
}
variables {
"number_of_repos": 3
}
Existem três etapas para usar variáveis:
-
Defina a variável fora da operação em um objeto
variáveis
:variables { "number_of_repos": 3 }
O objeto deve ser um JSON válido. Esse exemplo mostra um simples tipo de variável
Int
, mas é possível definir tipos de variáveis mais complexos, como objetos de entrada. Você também pode definir diversas variáveis aqui. -
Passe a variável para a operação como argumento:
query($number_of_repos:Int!){
O argumento é um par de chave-valor, em que a chave é o nome que começa com
$
(p. ex.,$number_of_repos
) e o valor é tipo (p. ex.,Int
). Adicione!
para indicar se o tipo é necessário. Se você definiu diversas variáveis, inclua-as aqui como múltiplos argumentos. -
Use a variável dentro da operação:
repositories(last: $number_of_repos) {
Neste exemplo, substituímos a variável pelo número de repositórios a ser recuperados. Especificamos um tipo na etapa 2, porque o GraphQL impõe uma digitação forte.
Este processo torna o argumento da consulta dinâmico. Agora, podemos simplesmente alterar o valor no objeto das variáveis
e manter o restante da consulta inalterada.
Usar variáveis como argumentos permite que você atualize valores dinamicamente no objeto das variáveis
sem alterar a consulta.
Exemplo de consulta
Vamos analisar uma questão mais complexa e colocar essas informações no contexto.
A consulta a seguir procura o repositório octocat/Hello-World
, encontra os 20 problemas fechados mais recentes e retorna o título, a URL e as primeiras 5 etiquetas de cada problema:
query {
repository(owner:"octocat", name:"Hello-World") {
issues(last:20, states:CLOSED) {
edges {
node {
title
url
labels(first:5) {
edges {
node {
name
}
}
}
}
}
}
}
}
Observando a composição linha por linha:
-
query {
Uma vez que queremos ler os dados do servidor, e não modificá-lo, a
consulta
é a operação-raiz. (Se você não especificar uma operação, aconsulta
também é o padrão.) -
repository(owner:"octocat", name:"Hello-World") {
Para começar a consulta, queremos encontrar um objeto do
repositório
. A validação do esquema indica que este objeto requer umproprietário
e um argumento donome
. -
issues(last:20, states:CLOSED) {
Para responder por todos os problemas no repositório, chamamos o objeto
problemas
. (Nós poderíamos realizar a consulta de um únicoproblema
em umrepositório
, mas isso exigiria que conhecêssemos o número do problema que desejamos retornar e que as apresentássemos como um argumento.)Alguns detalhes sobre o objeto
problemas
:- A documentação nos informa que esse objeto tem o tipo
IssueConnection
. - A validação de esquema indica que este objeto exige o
último
ouprimeiro
número dos resultados como argumento. Portanto, fornecemos20
. - A documentação também nos informa que esse objeto aceita um argumento
estados
, que é um enumIssueState
, que aceita os valoresABERTO
ouFECHADO
. Para encontrar apenas problemas fechados, conferimos à chaveestados
um valor deFECHADO
.
- A documentação nos informa que esse objeto tem o tipo
-
edges {
Sabemos que os
problemas
são uma conexão, porque têm o tipoIssueConnection
. Para recuperar dados sobre problemas individuais, temos de acessar o nó através dasbordas
. -
node {
Aqui, recuperamos o nó no fim da borda. A documentação da
IssueConnection
indica se o nó no final do tipoIssueConnection
é um objetoproblema
. -
Agora que sabemos que estamos recuperando um objeto
problema
, podemos ver a documentação e especificar os campos que desejamos retornar:title url labels(first:5) { edges { node { name } } }
Aqui, especificamos os campos
título
,url
eetiquetas
do objetoproblema
.O campo
etiquetas
tem o tipoLabelConnection
. Assim como no objetoproblemas
, porqueetiquetas
é uma conexão, devemos percorrer suas bordas para um nó conectado: o objetoetiqueta
. No nó, podemos especificar os campos de objetoetiqueta
que desejamos retornar, neste caso, onome
.
Você pode notar que executar essa consulta no repositório público do Octocat Hello-World
não retornará muitas etiquetas. Tente executá-la em um dos seus próprios repositórios que usam etiquetas, e provavelmente você verá uma diferença.
Exemplo de mutação
De modo geral, as mutações exigem informações que você só pode encontrar ao realizar primeiro uma consulta. Este exemplo mostra duas operações:
- Uma consulta para obter um ID do problema.
- Uma mutação para adicionar uma reação de emojis ao problema.
query FindIssueID {
repository(owner:"octocat", name:"Hello-World") {
issue(number:349) {
id
}
}
}
mutation AddReactionToIssue {
addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
reaction {
content
}
subject {
id
}
}
}
Embora você possa incluir uma consulta e uma mutação na mesma janela do Explorador, se der nome a elas (FindIssueID
e AddReactionToIssue
neste exemplo), as operações serão executadas como chamadas separadas para o ponto final do GraphQL. Não é possível realizar uma consulta junto com uma mutação ou vice-versa.
Vamos analisar o exemplo. A tarefa parece simples: adicione uma reação emoji a um problema.
Então, como é que sabemos começar com uma consulta? Ainda não sabemos.
Uma vez que desejamos modificar os dados no servidor (anexar um emoji a um problema), começamos procurando uma mutação útil no esquema. A documentação de referência mostra a mutação addReaction
com esta descrição: Adiciona uma reação a um assunto.
Perfeito!
A documentação para a lista de mutação lista três campos de entrada:
clientMutationId
(String
)subjectId
(ID!
)conteúdo
(ReactionContent!
)
Os sinais de!
indicam que subjectId
e conteúdo
são campos obrigatórios. O conteúdo
obrigatório tem sentido: desejamos adicionar uma reação. Portanto, precisamos especificar quais emojis devem ser usados.
Mas por que o subjectId
é obrigatório? Isso acontece porque o subjectId
é a única forma de identificar a qual o problema em qual repositório deve reagir.
É por isso que começamos este exemplo com uma consulta: para obter o ID
.
Vamos examinar a consulta linha por linha:
-
consulta FindIssueID {
Aqui estamos realizando uma consulta, que denominamos
FindIssueID
. Observe que nomear uma consulta é opcional; nós damos um nome aqui para que possamos incluí-la na mesma janela do explorador que a mutação. -
repository(owner:"octocat", name:"Hello-World") {
Especificamos o repositório realizando uma consulta no objeto do
repositório
e passando os argumentos do proprietárioe do <code>nome
. -
issue(number:349) {
Nós especificamos o problema a reagir, realizando uma consulta do objeto
problema
e passando um argumento donúmero
. -
id
Nesse ponto, recuperamos o
id
dehttps://github.com/octocat/Hello-World/issues/349
para passar comosubjectId
.
Ao realizarmos a consulta, obtemos o id
: MDU6SXNzdWUyMzEzOTE1NTE=
Observação: O id
retornado na consulta é o valor que passaremos como o subjectID
na mutação. Nem a documentação nem a introspecção do esquema indicará essa relação; você precisará entender os conceitos por trás dos nomes para descobrir isso.
Com a identificação conhecida, podemos prosseguir com a mutação:
-
mutation AddReactionToIssue {
Aqui, estamos realizando uma mutação que denominamos
AddReactionToIssue
. Tal como nas consultas, nomear uma mutação é opcional; aqui, damos um nome para que possamos incluí-la na mesma janela do explorador que a consulta. -
addReaction(input:{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}) {
Vamos examinar essa linha:
-
addReaction
é o nome da mutação. -
entrada
é a chave de argumento obrigatória. Isso sempre seráentrada
para uma mutação. -
{subjectId:"MDU6SXNzdWUyMzEzOTE1NTE=",content:HOORAY}
é o valor do argumento obrigatório. Este sempre será um objeto de entrada (daí as chaves) compostas de campos de entrada (subjectId
econteúdo
, neste caso) para uma mutação.Como sabemos qual o valor usar para o conteúdo? Os documentos
addReaction
nos dizem que o campo doconteúdo
tem o tipoReactionContent
, que é um enum, porque apenas algumas reações de emojis são compatíveis com em problemas no GitHub. Estes são os valores permitidos para reações (observe que alguns valores diferem de seus nomes de emojis correspondentes):conteúdo emoji +1
👍 -1
👎 laugh
😄 confused
😕 coração
❤️ hooray
🎉 rocket
🚀 eyes
👀
-
-
O resto da chamada é composto pelo objeto da carga. Aqui é onde especificamos os dados que desejamos que o servidor retorne depois de termos efetuado a mutação. Estas linhas vêm dos documentos
addReaction
, que são três possíveis campos de retorno:clientMutationId
(String
)reação
(Reação!
)assunto
(Reactable!
)
Neste exemplo, retornamos os dois campos obrigatórios (
reação
eassunto
), os quais exigiram subcampos (respectivamente,conteúdo
eid
).
Ao executarmos a mutação, esta é a resposta:
{
"data": {
"addReaction": {
"reaction": {
"content": "HOORAY"
},
"subject": {
"id": "MDU6SXNzdWUyMTc5NTQ0OTc="
}
}
}
}
Pronto! Confira sua reação para o problema passando o mouse sobre 🎉 para encontrar seu nome de usuário.
Observação final: quando você passa vários campos em um objeto de entrada, a sintaxe pode ficar pesada. Mover os campos para uma variável pode ajudar. Veja como você poderia reescrever a mutação original usando uma variável:
mutation($myVar:AddReactionInput!) {
"data": {
"addReaction": {
"reaction": {
"content": "HOORAY"
},
"subject": {
"id": "MDU6SXNzdWUyMTc5NTQ0OTc="
}
}
}
}
Você pode notar que o valor do campo conteúdo
no exemplo anterior (onde é usado diretamente na mutação) não tem aspas em torno de HORAY
, mas tem aspas quando usado na variável. Há um motivo para isso:
- Ao usar
conteúdo
diretamente na mutação, o esquema espera que o valor seja do tipoReactionContent
, que é um enum, não uma string. A validação de esquema causará um erro se você adicionar aspas no valor do enum, já que as aspas são reservadas para strings. - Ao usar
conteúdo
em uma variável, a seção de variáveis deve ser um JSON válido. Portanto, as aspas são necessárias. A validação de esquema interpreta corretamente o tipoReactionContent
quando a variável é passada para a mutação durante a execução.
Para obter mais informações sobre a diferença entre enums e strings, consulte as Especificações oficiais do GraphQL.
Leia mais
Há muito mais que você pode fazer ao formar chamadas do GraphQL. Aqui estão alguns lugares para procurar a seguir: