Pular para o conteúdo

Lavra

A consulta tipada do DataForge: o cliente diz exatamente quais campos quer, e recebe exatamente aqueles.

Lavra é a consulta tipada do DataForge. O cliente diz exatamente o que precisa, numa consulta, e recebe exatamente aquilo — nem um campo a mais, nem uma segunda chamada para buscar o que faltou.

consulta lavra
busca:
    usuario(id: 7):
        nome
        pedidos(limite: 3):
            numero
            total

Uma rota REST devolve o que o servidor decidiu devolver. Quem precisa de menos carrega o resto; quem precisa de mais faz outra chamada. Numa tela de celular com rede ruim, as duas coisas custam.

A consulta escolhe os ramos. O grafo inteiro existe; a resposta traz só o caminho pedido. Os ramos apagados não são buscados.

O nome#

Lavra é a extração de um veio de minério — e lavrar também é redigir um documento. As duas coisas que este módulo faz: um esquema é lavrado, e a consulta lavra dele exatamente o minério que quer. Segue a metáfora da forja, como Kiln, Crucible e Vitrine.

O esquema nasce dos seus records#

Esta é a decisão que define o módulo. Não há uma segunda linguagem de esquema ao lado da linguagem:

dataforge
record Usuario:
    id: Integer
    nome: String
    email: String

esq := Lavra.esquema("loja")
Lavra.tipo(esq, Usuario)

O GraphQL precisa de um SDL próprio porque o servidor pode estar escrito em qualquer coisa, e o esquema tem de existir fora dela. Aqui o servidor é DataForge, e o record já diz nome, campo e tipo. Um arquivo de esquema ao lado seria uma segunda fonte de verdade para divergir da primeira.

A consulta é indentada#

Porque a linguagem é. Uma consulta escrita ao lado do código que a usa tem de parecer com ele — e o : no fim marca "isto tem seleção dentro", exatamente como em given, cycle e action.

GraphQLLavra
{ … }indentação
querybusca
mutationmudanca
subscriptionassinatura
typetipo
inputentrada
interfacecontrato
unionuniao
scalarescalar
fragment X on Ttrecho X em T
...X...X
... on T { }... em T:
@include(if:)@incluir(se:)
@skip(if:)@pular(se:)
$v: T = padrão$v: T := padrão
! e [ ]iguais

! e [ ] são a única coisa emprestada da escrita do GraphQL, e de propósito: quem já conhece lê sem aprender nada, e quem não conhece aprende dois símbolos.

Um exemplo inteiro#

dataforge
adopt Arcane.Lavra as Lavra

record Usuario:
    id: Integer
    nome: String
    email: String

usuarios := [Usuario(1, "Ana", "ana@forja.co"), Usuario(2, "Bia", "bia@forja.co")]

esq := Lavra.esquema("loja")
Lavra.tipo(esq, Usuario)
Lavra.campo(esq, "Usuario", "nome", "String!")

action achar(raiz, args, ctx):
    achados := [u cycle u in usuarios given u.id is args["id"]]
    yield achados[0] given len(achados) bigger 0 otherwise void

Lavra.busca(esq, "usuario", "Usuario", args := {"id": "Integer!"}, resolve := achar)
Lavra.conferir(esq)

r := Lavra.executar(esq, """
busca:
    usuario(id: 1):
        nome
""")

out r["dados"]
text
{usuario: {nome: Ana}}

O que ele traz#

AssuntoPágina
Tipos, campos, argumentos, nulidade, listasO esquema
Enums, entradas, escalares, contratos, uniõesO esquema
Busca, mudança, assinatura, apelidosA consulta
Trechos, variáveis, diretivas, introspecçãoA consulta
Resolvedores, contexto, erros, autorizaçãoResolvedores
Lote contra o N+1, paginação, cacheDesempenho
Validação, limites, rate limit, observabilidadeSegurança
HTTP, WebSocket, tempo real, clienteO servidor
Vários serviços, portão, composiçãoFederação
CRUD, banco, DDD, testes, deploy, CINa prática

O que ele NÃO é#

Lavra não é GraphQL. Não fala o protocolo do GraphQL, não lê arquivos de SDL, e uma ferramenta de GraphQL não conversa com ele. As ideias são as mesmas — e são boas —, a escrita é a do DataForge.

Ele também não é um planejador de consulta distribuído: a federação compõe esquemas e resolve a fronteira com o lote, e não com um plano de execução entre serviços. Um subconjunto pela metade seria pior que a honestidade de não ter.