8 minutos
GraphQL Validations Migration Guide
Em breve, o graph-node
apoiará a cobertura total da especificação de Validações GraphQL.
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.
Guia de migração
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.
Not all Subgraphs will need to be migrated, if you are using GraphQL ESlint or GraphQL Code Generator, they already ensure that your queries are valid.
Ferramenta CLI de migração
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 @graphql-validate/cli
é uma ferramenta CLI (interface de linha de comando) simples que ajuda a validar operações GraphQL perante um schema.
Primeiros passos
Pode executar a ferramenta da seguinte forma:
1npx @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:
artblocks/art-blocks
- A URL de prévia do schema (https://api-next.thegraph.com/) 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:
.graphql
,.ts
,.tsx
,.js
,jsx
(-o
option).
Output em CLI
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).
Execute os seus queries locais contra o schema de prévia
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 GraphiQL, e testar o seu query. Estas ferramentas também marcarão tais erros na sua interface, antes mesmo de executá-la.
Como resolver problemas
Abaixo, encontrará todos os erros de validação GraphQL que podem ocorrer nas suas operações em GraphQL.
Variáveis, operações, fragments, ou argumentos devem ser originais
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)
1# A seguinte operação violou a regra UniqueOperationName2# já que temos uma operação única com 2 queries3# com o mesmo nome4query myData {5 id6}78query myData {9 name10}
Solução:
1query myData {2 id3}45query myData2 {6 # renomeie o segundo query7 name8}
Nome de Fragment duplicado (#UniqueFragmentNamesRule)
1# A seguinte operação violou a regra de2# UniqueFragmentName.3query myData {4 id5 ...MyFields6}78fragment MyFields {9 metadata10}1112fragment MyFields {13 name14}
Solução:
1query myData {2 id3 ...MyFieldsName4 ...MyFieldsMetadata5}67fragment MyFieldsMetadata { # dê um nome único ao fragmento8 metadata9}1011fragment MyFieldsName { # dê um nome único ao fragmento12 name13}
Nome de variável duplicado (#UniqueVariableNamesRule)
1# A seguinte operação viola a UniqueVariables2query myData($id: String, $id: Int) {3 id4 ...MyFields5}
Solução:
1query myData($id: String) {2 # mantenha a variável relevante (here: `$id: String`)3 id4 ...MyFields5}
Nome de argumento duplicado (#UniqueArgument)
1# A seguinte operação violou a UniqueArguments2query myData($id: ID!) {3 userById(id: $id, id: "1") {4 id5 }6}
Solução:
1query myData($id: ID!) {2 userById(id: $id) {3 id4 }5}
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:
1# Isto falhará se executado junto com uma2# operação única com os dois queries a seguir:3query {4 someField5}67query {8 otherField9}
Solução:
1query {2 someField3 otherField4}
Ou nomeie os dois queries:
1query FirstQuery {2 someField3}45query SecondQuery {6 otherField7}
Campos sobrepostos
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)
1# Dar apelidos a campos pode causar conflitos,2# seja com outros apelidos ou outros campos que3# existam no schema GraphQL.4query {5 dogs {6 name: nickname7 name8 }9}
Solução:
1query {2 dogs {3 name: nickname4 originalName: name # apelide o campo `name` original5 }6}
Conflicting fields with arguments (#OverlappingFieldsCanBeMergedRule) (Campos em conflito com argumentos)
1# Argumentos diferentes podem levar a dados diferentes,2# então não podemos presumir que os campos serão os mesmos.3query {4 dogs {5 doesKnowCommand(dogCommand: SIT)6 doesKnowCommand(dogCommand: HEEL)7 }8}
Solução:
1query {2 dogs {3 knowsHowToSit: doesKnowCommand(dogCommand: SIT)4 knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)5 }6}
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:
1query {2 # Eventualmente, temos duas definições "x",3 # a apontar para campos diferentes!4 ...A5 ...B6}78fragment A on Type {9 x: a10}1112fragment B on Type {13 x: b14}
Além disso, diretivas client-side no GraphQL como @skip
e @include
podem levar a ambiguidades, por exemplo:
1fragment mergeSameFieldsWithSameDirectives on Dog {2 name @include(if: true)3 name @include(if: false)4}
Leia mais sobre o algoritmo aqui.
Variáveis ou Fragments Não Usados
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)
1# Inválida, porque o $someVar nunca é usado.2query something($someVar: String) {3 someData4}
Solução:
1query something {2 someData3}
Fragment sem uso (#NoUnusedFragmentsRule)
1# Inválida, porque o fragmento AllFields nunca é usado.2query something {3 someData4}56fragment AllFields { # unused :(7 name8 age9}
Solução:
1# Inválida, porque o fragmento AllFields nunca é usado.2query something {3 someData4}56# retire o fragmento `AllFields`
Conjunto de seleção inválido ou em falta (#ScalarLeafsRule)
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:
1type Image {2 url: String!3}45type User {6 id: ID!7 avatar: Image!8}910type Query {11 user: User!12}
Conjunto de seleções inválido
1query {2 user {3 id { # Inválido por que "id" é do tipo ID e não tem subcampos45 }6 }7}
Solução:
1query {2 user {3 id4 }5}
Conjunto de seleções em falta
1query {2 user {3 id4 image # `image` exige um conjunto de seleção para subcampos!5 }6}
Solução:
1query {2 user {3 id4 image {5 src6 }7 }8}
Valores de Arguments incorretos (#VariablesInAllowedPositionRule)
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:
1query purposes {2 # Se o "name" for definido como "String" no schema,3 # esta consulta falhará durante a validação.4 purpose(name: 1) {5 id6 }7}89# Isto também pode acontecer quando uma variável incorreta é definida:1011query purposes($name: Int!) {12 # Se o "name" for definido como `String` no schema,13 # esta consulta falhará durante a validação, porque a14 # variável usada é do tipo `Int`15 purpose(name: $name) {16 id17 }18}
Tipo, Varíavel, Fragment, ou Diretiva desconhecido (#UnknownX)
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: invalid spread or definition
(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
:
1query {2 dog {3 ...CatSimple4 }5}67fragment CatSimple on Cat {8 # ...9}
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.
1fragment fragOnScalar on Int {2 # não podemos definir um fragment sobre um scalar (`Int`)3 something4}56fragment inlineFragOnScalar on Dog {7 ... on Boolean {8 # `Boolean` não é um subtipo de `Dog`9 somethingElse10 }11}
Uso de Diretivas
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:
1query {2 dog {3 name @include(true)4 age @skip(true)5 }6}
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):
1query {2 dog {3 name @include(true) @include(true)4 }5}