Guia de migração de Validações GraphQL
Reading time: 8 min
Em breve, o graph-node
apoiará a cobertura total da .
As versões anteriores do graph-node
não apoiavam todas as validações, e forneciam respostas mais suaves — então, em casos de ambiguidade, o graph-node
ignorava componentes de operação inválidos do GraphQL.
O apoio a Validações do GraphQL é o pilar para os futuros novos recursos e o desempenho em escala da Graph Network.
Ele também garantirá o determinismo de respostas de consultas, um requisito importante na Graph Network.
Ativar as Validações GraphQL quebrará alguns queries existentes enviadas à API do The Graph.
Para cumprir tais validações, por favor siga o guia de migração.
⚠️ Se não migrar os seus queries antes de ativar as validações, eles retornarão erros e possivelmente quebrarão os seus frontends/clientes.
Pode usar a ferramenta de migração em CLI para encontrar e consertar quaisquer problemas nas suas operações no GraphQL. De outra forma, pode atualizar o endpoint do seu cliente GraphQL para usar o endpoint https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME
. Testar os seus queries perante este endpoint ajudará-lhe a encontrar os problemas neles presentes.
Nem todos os Subgraphs precisam ser migrados; se usar o ou o , eles já garantirão que os seus queries sejam válidos.
A maioria dos erros de operação em GraphQL podem ser encontrados na sua base de código com antecedência.
Portanto, provemos uma experiência suave para validar as suas operações GraphQL durante a programação ou em CI.
O é uma ferramenta CLI (interface de linha de comando) simples que ajuda a validar operações GraphQL perante um schema.
Pode executar a ferramenta da seguinte forma:
npx @graphql-validate/cli -s https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME -o *.graphql
Notas:
- Configure ou substitua $GITHUB_USER e $SUBGRAPH_NAME com os valores adequados. Por exemplo:
- A URL de prévia do schema () fornecida tem um rate-limit alto e será aposentada quando todos os utilizadores migrarem à versão nova. Não a use na produção.
- As operações são identificadas em arquivos com as seguintes extensões: (
-o
option).
A ferramenta de CLI [@graphql-validate/cli](https://github.com/saihaj/graphql-validate)
mostrará quaisquer erros de operação em GraphQL na seguinte forma:
Para cada erro, serão exibidos uma descrição, caminho e posição de arquivo, e um atalho para um exemplo de solução (veja a secção seguinte).
Nós fornecemos um endpoint https://api-next.thegraph.com/
que executa uma versão graph-node
com as validações ativadas.
Para testar queries, é só enviá-las para:
https://api-next.thegraph.com/subgraphs/id/<Qm...>
ou
https://api-next.thegraph.com/subgraphs/name/<GITHUB_USER>/<SUBGRAPH_NAME>
Para trabalhar com consultas marcadas com erros de validação, pode usar a sua ferramenta de query no GraphQL favorita, como Altair ou , e testar o seu query. Estas ferramentas também marcarão tais erros na sua interface, antes mesmo de executá-la.
Abaixo, encontrará todos os erros de validação GraphQL que podem ocorrer nas suas operações em GraphQL.
Nós aplicamos regras para garantir que uma operação inclua um conjunto único de variáveis, operações, fragmentos e argumentos.
Uma operação GraphQL só é válida se não conter nenhuma ambiguidade.
Para alcançar isto, devemos garantir que alguns componentes na sua operação GraphQL sejam únicos e originais.
Veja algumas operações inválidas que violam estas regras:
Nome duplicado de Query (#UniqueOperationNamesRule)
# A seguinte operação violou a regra UniqueOperationName# já que temos uma operação única com 2 queries# com o mesmo nomequery myData {id}query myData {name}
Solução:
query myData {id}query myData2 {# renomeie o segundo queryname}
Nome de Fragment duplicado (#UniqueFragmentNamesRule)
# A seguinte operação violou a regra de# UniqueFragmentName.query myData {id...MyFields}fragment MyFields {metadata}fragment MyFields {name}
Solução:
query myData {id...MyFieldsName...MyFieldsMetadata}fragment MyFieldsMetadata { # dê um nome único ao fragmentometadata}fragment MyFieldsName { # dê um nome único ao fragmentoname}
Nome de variável duplicado (#UniqueVariableNamesRule)
# A seguinte operação viola a UniqueVariablesquery myData($id: String, $id: Int) {id...MyFields}
Solução:
query myData($id: String) {# mantenha a variável relevante (here: `$id: String`)id...MyFields}
Nome de argumento duplicado (#UniqueArgument)
# A seguinte operação violou a UniqueArgumentsquery myData($id: ID!) {userById(id: $id, id: "1") {id}}
Solução:
query myData($id: ID!) {userById(id: $id) {id}}
Query anónimo duplicado (#LoneAnonymousOperationRule)
Aliás, usar duas operações anónimas violará a regra LoneAnonymousOperation
devido a um conflito na estrutura das respostas:
# Isto falhará se executado junto com uma# operação única com os dois queries a seguir:query {someField}query {otherField}
Solução:
query {someFieldotherField}
Ou nomeie os dois queries:
query FirstQuery {someField}query SecondQuery {otherField}
Uma seleção GraphQL só é considerada válida se ela resolver corretamente o conjunto eventual de resultados.
Se um conjunto de seleção, ou um campo, em específico criar ambiguidades, seja pelo campo selecionado ou pelos argumentos usados, o serviço GraphQL não conseguirá validar a operação.
Aqui estão alguns exemplos de operações inválidas que violam esta regra:
Apelidos de campos em conflito (#OverlappingFieldsCanBeMergedRule)
# Dar apelidos a campos pode causar conflitos,# seja com outros apelidos ou outros campos que# existam no schema GraphQL.query {dogs {name: nicknamename}}
Solução:
query {dogs {name: nicknameoriginalName: name # apelide o campo `name` original}}
Conflicting fields with arguments (#OverlappingFieldsCanBeMergedRule) (Campos em conflito com argumentos)
# Argumentos diferentes podem levar a dados diferentes,# então não podemos presumir que os campos serão os mesmos.query {dogs {doesKnowCommand(dogCommand: SIT)doesKnowCommand(dogCommand: HEEL)}}
Solução:
query {dogs {knowsHowToSit: doesKnowCommand(dogCommand: SIT)knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)}}
Aliás, em casos de uso mais complexos, é possível violar esta regra ao usar dois fragmentos que possam causar um conflito no conjunto esperado afinal:
query {# Eventualmente, temos duas definições "x",# a apontar para campos diferentes!...A...B}fragment A on Type {x: a}fragment B on Type {x: b}
Além disso, diretivas client-side no GraphQL como @skip
e @include
podem levar a ambiguidades, por exemplo:
fragment mergeSameFieldsWithSameDirectives on Dog {name @include(if: true)name @include(if: false)}
Uma operação GraphQL só é considerada válida se todos os componentes definidos pela operação (variáveis, fragments) forem usados.
Veja alguns exemplos de operações GraphQL que violam estas regras:
Variável sem uso (#NoUnusedVariablesRule)
# Inválida, porque o $someVar nunca é usado.query something($someVar: String) {someData}
Solução:
query something {someData}
Fragment sem uso (#NoUnusedFragmentsRule)
# Inválida, porque o fragmento AllFields nunca é usado.query something {someData}fragment AllFields { # unused :(nameage}
Solução:
# Inválida, porque o fragmento AllFields nunca é usado.query something {someData}# retire o fragmento `AllFields`
Aliás, uma seleção de campo GraphQL só é válida se o seguinte for validado:
- Um campo de objeto deve ter um conjunto de seleção especificado.
- Um campo de margem (scalar, enum) não deve ter um conjunto de seleção especificado.
Aqui estão alguns exemplos de violações destas regras com o seguinte Schema:
type Image {url: String!}type User {id: ID!avatar: Image!}type Query {user: User!}
Conjunto de seleções inválido
query {user {id { # Inválido por que "id" é do tipo ID e não tem subcampos}}}
Solução:
query {user {id}}
Conjunto de seleções em falta
query {user {idimage # `image` exige um conjunto de seleção para subcampos!}}
Solução:
query {user {idimage {src}}}
Operações GraphQL que passam valores em código rígido para argumentos devem ser válidas, com base no valor definido no schema.
Aqui estão alguns exemplos de operações inválidas que violam estas regras:
query purposes {# Se o "name" for definido como "String" no schema,# esta consulta falhará durante a validação.purpose(name: 1) {id}}# Isto também pode acontecer quando uma variável incorreta é definida:query purposes($name: Int!) {# Se o "name" for definido como `String` no schema,# esta consulta falhará durante a validação, porque a# variável usada é do tipo `Int`purpose(name: $name) {id}}
A API do GraphQL levantará um erro se houver uso de qualquer tipo, variável, fragmento ou diretiva desconhecidos.
Estas referências desconhecidas devem ser consertadas:
- renomeie se for um erro gramatical
- caso contrário, remova
(Fragment: espalhamento ou definição inválidos)
Invalid Fragment spread (#PossibleFragmentSpreadsRule) (Espalhamento de fragment inválido)
Um Fragment não pode ser espalhado em um tipo não aplicável.
Por exemplo, não podemos aplicar um fragmento Cat
no tipo Dog
:
query {dog {...CatSimple}}fragment CatSimple on Cat {# ...}
Definição de Fragment inválida (#FragmentsOnCompositeTypesRule)
Todos os Fragments devem ser definidos sobre um tipo composto (com on ...
), ou seja: objeto, interface ou união.
Os seguintes exemplos são inválidos, já que definir fragments em scalars é inválido.
fragment fragOnScalar on Int {# não podemos definir um fragment sobre um scalar (`Int`)something}fragment inlineFragOnScalar on Dog {... on Boolean {# `Boolean` não é um subtipo de `Dog`somethingElse}}
Directive cannot be used at this location (#KnownDirectivesRule) (A diretiva não pode ser usada neste local)
Apenas diretivas GraphQL (@...
) apoiadas pela API do The Graph podem ser usadas.
Aqui está um exemplo com as diretivas apoiadas pelo GraphQL:
query {dog {name @include(true)age @skip(true)}}
Nota: @stream
, @live
, e @defer
não têm apoio.
Directive can only be used once at this location (#UniqueDirectivesPerLocationRule) (A diretiva só pode ser usada neste local uma vez)
As diretivas apoiadas pelo The Graph só podem ser usadas uma vez por local.
O seguinte é inválido (e redundante):
query {dog {name @include(true) @include(true)}}