Guide de migration des validations GraphQL
Reading time: 9 min
Bientôt, graph-node
supportera 100% de la couverture de la [Spécification des validations GraphQL] ().
Les versions précédentes de graph-node
ne prenaient pas en charge toutes les validations et fournissaient des réponses plus gracieuses - ainsi, en cas d'ambiguïté, graph-node
ignorait les composants d'opérations GraphQL non valides.
La prise en charge de GraphQL Validations est le pilier des nouvelles fonctionnalités à venir et des performances à grande échelle de The Graph Network.
Il garantira également le déterminisme des réponses aux requêtes, une exigence clé sur The Graph Network.
L'activation des validations GraphQL interrompra certaines requêtes existantes envoyées à l'API Graph.
Pour être conforme à ces validations, veuillez suivre le guide de migration.
⚠️ Si vous ne migrez pas vos requêtes avant le déploiement des validations, elles renverront des erreurs et éventuellement casseront vos frontends/clients.
Vous pouvez utiliser l'outil de migration CLI pour rechercher tous les problèmes dans vos opérations GraphQL et les résoudre. Vous pouvez également mettre à jour le point de terminaison de votre client GraphQL pour utiliser le point de terminaison « ». Tester vos requêtes sur ce point de terminaison vous aidera à trouver les problèmes dans vos requêtes.
Tous les subgraphs n'auront pas besoin d'être migrés si vous utilisez ou [GraphQL Code Generator]( /graphql/codegen), ils garantissent déjà que vos requêtes sont valides.
La plupart des erreurs d'opérations GraphQL peuvent être trouvées à l'avance dans votre base de code.
Pour cette raison, nous offrons une expérience fluide pour valider vos opérations GraphQL pendant le développement ou dans CI.
est un outil CLI simple qui permet de valider les opérations GraphQL par rapport à un schéma donné.
Vous pouvez exécuter l'outil comme suit :
npx @graphql-validate/cli -s https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME -o *.graphql
Notes:
- Définissez ou remplacez $GITHUB_USER, $SUBGRAPH_NAME par les valeurs appropriées. Comme :
- L'URL du schéma d'aperçu () fournie est fortement limitée en débit et sera supprimée une fois que tous les utilisateurs auront migré vers la nouvelle version. Ne l'utilisez pas en production.
- Les opérations sont identifiées dans les fichiers avec les extensions suivantes (option
-o
).
L'outil CLI [@graphql-validate/cli](https://github.com/saihaj/graphql-validate)
affichera toutes les erreurs d'opérations GraphQL comme suit :
Pour chaque erreur, vous trouverez une description, le chemin et la position du fichier, ainsi qu'un lien vers un exemple de solution (voir la section suivante).
Nous fournissons un point de terminaison « » qui exécute une version « graph-node » dont les validations sont activées.
Vous pouvez tester des requêtes en les envoyant à :
https://api-next.thegraph.com/subgraphs/id/<Qm...>
ou bien
https://api-next.thegraph.com/subgraphs/name/<GITHUB_USER>/<SUBGRAPH_NAME>
Pour travailler sur des requêtes signalées comme comportant des erreurs de validation, vous pouvez utiliser votre outil de requête GraphQL préféré, comme Altair ou , et essayer votre requête. Ces outils marqueront également ces erreurs dans leur interface utilisateur, avant même que vous ne l'exécutiez.
Ci-dessous, vous trouverez toutes les erreurs de validation GraphQL qui pourraient survenir sur vos opérations GraphQL existantes.
Nous avons appliqué des règles pour garantir qu'une opération inclut un ensemble unique de variables, d'opérations, de fragments et d'arguments GraphQL.
Une opération GraphQL n'est valide que si elle ne contient aucune ambiguïté.
Pour y parvenir, nous devons nous assurer que certains composants de votre opération GraphQL doivent être uniques.
Voici un exemple de quelques opérations non valides qui enfreignent ces règles :
Nom de requête en double (#UniqueOperationNamesRule)
# L'opération suivante a violé UniqueOperationName# règle, puisque nous avons une seule opération avec 2 requêtes# avec le même nomquery myData {id}query myData {name}
Solution:
query myData {id}query myData2 {# renommer la deuxième requêtename}
Nom de fragment en double (#UniqueFragmentNamesRule)
# L'opération suivante a violé la règle UniqueFragmentNamequery myData {id...MyFields}fragment MyFields {metadata}fragment MyFields {name}
Solution:
query myData {id...MyFieldsName...MyFieldsMetadata}fragment MyFieldsMetadata { # assigner un nom unique au fragmentmetadata}fragment MyFieldsName { # assigner un nom unique au fragmentnom}
Variable en double (#UniqueVariableNamesRule)
# L'opération suivante viole le UniqueVariablesquery myData($id: String, $id: Int) {id...MyFields}
Solution:
query myData($id: String) {# conserver la variable pertinente (ici : `$id: String`)id...MyFields}
Nom d'argument en double (#UniqueArgument)
# L'opération suivante a violé les UniqueArgumentsquery myData($id: ID!) {userById(id: $id, id: "1") {id}}
Solution:
query myData($id: ID!) {userById(id: $id) {id}}
Requête anonyme en double (#LoneAnonymousOperationRule)
De plus, l'utilisation de deux opérations anonymes violera la règle « LoneAnonymousOperation » en raison d'un conflit dans la structure de réponse :
# Cela échouera s'il est exécuté ensemble dans# une seule opération avec les deux requêtes suivantes :query {someField}query {otherField}
Solution:
query {someFieldotherField}
Ou nommez les deux requêtes :
query FirstQuery {someField}query SecondQuery {otherField}
Un jeu de sélection GraphQL n'est considéré comme valide que s'il résout correctement l'éventuel jeu de résultats.
Si un ensemble de sélection spécifique, ou un champ, crée une ambiguïté soit par le champ sélectionné, soit par les arguments utilisés, le service GraphQL ne parviendra pas à valider l'opération.
Voici quelques exemples d'opérations non valides qui enfreignent cette règle :
Conflit d'alias de champs (#OverlappingFieldsCanBeMergedRule)
# L'alias des champs peut provoquer des conflits, soit avec# d'autres alias ou d'autres champs qui existent sur le# Schéma GraphQL.query {dogs {name: nicknamename}}
Solution:
query {dogs {nickname: nameoriginalName: name # alias du champ `name` original}}
*Champs en conflit avec des arguments (#OverlappingFieldsCanBeMergedRule)
# Différents arguments peuvent conduire à des données différentes,# donc nous ne pouvons pas supposer que les champs seront les mêmes.query {dogs {doesKnowCommand(dogCommand: SIT)doesKnowCommand(dogCommand: HEEL)}}
Solution:
query {dogs {knowsHowToSit: doesKnowCommand(dogCommand: SIT)knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)}}
De plus, dans des cas d'utilisation plus complexes, vous pourriez enfreindre cette règle en utilisant deux fragments susceptibles de provoquer un conflit dans l'ensemble finalement attendu :
query {# Finalement, nous avons deux définitions de "x", pointant# vers des champs différents !...A...B}fragment A on Type {x: a}fragment B on Type {x: b}
En plus de cela, les directives GraphQL côté client comme @skip
et @include
peuvent conduire à une ambiguïté, par exemple :
fragment mergeSameFieldsWithSameDirectives on Dog {name @include(if: true)name @include(if: false)
Une opération GraphQL n'est également considérée comme valide que si tous les composants définis par l'opération (variables, fragments) sont utilisés.
Voici quelques exemples d'opérations GraphQL qui enfreignent ces règles :
Variable inutilisée (#NoUnusedVariablesRule)
# Invalide, car $someVar n'est jamais utilisé.query something($someVar: String) {someData}
Solution:
query something {someData}
Fragment inutilisé (#NoUnusedFragmentsRule)
# Invalide, car le fragment AllFields n'est jamais utilisé.query something {someData}fragment AllFields { # inutilisé :(nameage}
Solution:
# Invalide, car le fragment AllFields n'est jamais utilisé.query something {someData}# retirer le fragment `AllFields`
De plus, une sélection de champ GraphQL n'est valide que si les éléments suivants sont validés :
- Un champ d'objet doit avoir un ensemble de sélection spécifié.
- Un champ de bord (scalaire, énumération) ne doit pas avoir de jeu de sélection spécifié.
Voici quelques exemples de violations de ces règles avec le schéma suivant :
type Image {url: String!}type User {id: ID!avatar: Image!}type Query {user: User!}
Ensemble de sélection invalide
query {user {id { # Invalide, car "id" est de type ID et n'a pas de sous-champs}}}
Solution:
query {user {id}}
Ensemble de sélection manquant
query {user {idimage # `image` nécessite un ensemble de sélection pour les sous-champs!}}
Solution:
query {user {idimage {src}}}
Les opérations GraphQL qui transmettent des valeurs codées en dur aux arguments doivent être valides, en fonction de la valeur définie dans le schéma.
Voici quelques exemples d'opérations non valides qui enfreignent ces règles :
query purposes {# Si "name" est défini comme "String" dans le schéma,# cette requête échouera lors de la validation.purpose(name: 1) {id}}# Cela pourrait également se produire lorsqu'une variable incorrecte est définie :query purposes($name: Int!) {# Si "name" est défini comme `String` dans le schéma,# cette requête échouera lors de la validation, car la# variable utilisée est de type `Int`purpose(name: $name) {id}}
L'API GraphQL générera une erreur si un type, une variable, un fragment ou une directive inconnu est utilisé.
Ces références inconnues doivent être corrigées :
- renommer si c'était une faute de frappe
- sinon, supprimez
Propagation de fragments non valide (#PossibleFragmentSpreadsRule)
Un Fragment ne peut pas être réparti sur un type non applicable.
Exemple, nous ne pouvons pas appliquer un fragment Cat
au type Dog
:
query {dog {...CatSimple}}fragment CatSimple on Cat {# ...}
Définition de fragment non valide (#FragmentsOnCompositeTypesRule)
Tout Fragment doit être défini sur (en utilisant on ...
) un type composite, en bref : objet, interface ou union.
Les exemples suivants ne sont pas valides, car la définition de fragments sur des scalaires n'est pas valide.
fragment fragOnScalar on Int {# nous ne pouvons pas définir un fragment sur un scalaire (`Int`)something}fragment inlineFragOnScalar on Dog {... on Boolean {# `Boolean` n'est pas un sous-type de `Dog`somethingElse}}
La directive ne peut pas être utilisée à cet emplacement (#KnownDirectivesRule)
Seules les directives GraphQL (« @... ») prises en charge par l'API Graph peuvent être utilisées.
Voici un exemple avec les directives prises en charge par GraphQL :
query {dog {name @include(true)age @skip(true)}}
Remarque : @stream
, @live
, @defer
ne sont pas pris en charge.
La directive ne peut être utilisée qu'une seule fois à cet emplacement (#UniqueDirectivesPerLocationRule)
Les directives prises en charge par The Graph ne peuvent être utilisées qu'une seule fois par emplacement.
Ce qui suit n'est pas valide (et redondant) :
query {dog {name @include(true) @include(true)}}
Comment résoudre les problèmes
#Lien vers cette section