A consulta
A linguagem que o cliente escreve: busca, mudança, assinatura, apelidos, trechos, variáveis, diretivas e introspecção.
A consulta é um texto — ela atravessa a rede. A escrita é indentada, como a linguagem, e o : no fim marca que aquele campo tem seleção dentro.
As três operações#
| Operação | Para quê |
|---|---|
busca | ler — sem efeito colateral |
mudanca | escrever — o efeito aparece no nome |
assinatura | acompanhar — o servidor empurra cada novo valor |
A separação não é burocracia. Quem lê a consulta sabe, sem abrir o resolvedor, se aquilo muda alguma coisa — e é o que permite a um intermediário guardar em cache uma busca e nunca uma mudanca.
busca:
usuario(id: 1):
nome
mudanca:
criarUsuario(dados: {nome: "Ana", email: "ana@forja.co"}):
id
assinatura:
pedidoCriado:
numero
totalCampos e argumentos#
busca:
pedidos(limite: 10, ordem: Recente, ativo: yes):
numero
itens:
quantidade
produto:
nomeUm campo sem seleção é uma folha (numero); um com seleção termina em :. É a mesma regra do bloco na linguagem, e o erro de esquecer os dois pontos diz isso.
Os valores aceitos são os da linguagem: texto entre aspas, número, yes/no/void, [lista], {vault}, $variavel e o nome de um membro de enum.
Apelidos#
busca:
ana: usuario(id: 1):
nome
bia: usuario(id: 2):
nome{ana: {nome: Ana}, bia: {nome: Bia}}Sem apelido, os dois usuario colidiriam na resposta. É também como se pede o mesmo campo com argumentos diferentes na mesma consulta.
Trechos#
Um trecho é um pedaço de seleção com nome. Ele existe para não repetir a mesma lista de campos em cinco lugares — e para que mudá-la seja uma edição só.
trecho Basico em Usuario:
id
nome
email
busca:
ana: usuario(id: 1):
...Basico
bia: usuario(id: 2):
...Basico
criado_emO em Usuario diz a que tipo ele se aplica, e é o que permite conferi-lo antes de rodar: um trecho de Usuario usado num Produto é recusado pela validação.
Trecho condicional#
Para união e contrato: pedir o que só existe num dos tipos.
busca:
acervo:
titulo
... em Video:
minutos
... em Podcast:
episodioVariáveis#
A consulta é uma só; o valor muda. É o que permite guardá-la como constante no cliente em vez de montá-la com concatenação — que é de onde vem injeção.
busca Painel($id: Integer!, $limite: Integer := 3):
usuario(id: $id):
nome
pedidos(limite: $limite):
numeror := Lavra.executar(esq, consulta, variaveis := {"id": 7})| Declaração | O que acontece se não vier |
|---|---|
$id: Integer! | a consulta é recusada |
$id: Integer | chega como void |
$id: Integer := 3 | chega como 3 |
Diretivas#
busca Talvez($detalhado: Boolean!):
usuario(id: 1):
nome
email @incluir(se: $detalhado)
telefone @pular(se: $detalhado)@incluir(se:) põe o campo quando a condição é verdadeira; @pular(se:) tira. Servem para uma consulta só atender a duas telas — a compacta e a completa — sem duas versões dela para divergirem.
Diretivas próprias entram no esquema:
action so_admin(args, ctx):
yield ctx["papel"] is "admin"
Lavra.diretiva(esq, "admin", so_admin)busca:
usuario(id: 1):
nome
cpf @adminÉ o gancho para @admin, @experimento(nome: …) e afins — sem espalhar given por dentro de cada resolvedor.
Introspecção#
O esquema se descreve, e é ele mesmo quem responde:
busca:
__tipo(nome: "Pedido")busca:
__esquemaSem introspecção, um cliente precisa de documentação ao lado para saber o que pedir — e essa documentação envelhece em silêncio. Com ela, o editor completa o campo e a página de referência é gerada do que está no ar.
A resposta vem do mesmo objeto que executa. Não há um segundo lugar descrevendo o esquema para divergir do primeiro.
Os erros de consulta dizem a linha#
erro: 'Usuario' não tem o campo 'nomee'
linha 3
dica: você quis dizer 'nome'?E todos de uma vez: um validador que para no primeiro erro faz corrigir uma linha por tentativa. Com dez numa resposta, corrigem-se as dez.