8 minutes
GraphQL Validations Migration Guide
Presto graph-node
supporterà il 100% di copertura delle specifiche [Specifiche delle validation GraphQL] (https://spec.graphql.org/June2018/#sec-Validation).
Le versioni precedenti di graph-node
non supportavano tutte le validation e fornivano risposte più aggraziate, per cui, in caso di ambiguità, graph-node
ignorava i componenti delle operazioni GraphQL non validi.
Il supporto delle validation GraphQL è il pilastro delle nuove funzionalità e delle prestazioni su scala di The Graph Network.
Garantirà inoltre il determinismo delle risposte alle query, un requisito fondamentale per The Graph Network.
L’abilitazione delle validation GraphQL interromperà alcune query esistenti inviate all’API The Graph.
Per essere conformi a tali validation, seguire la guida alla migrazione.
⚠️ Se non si migrano le query prima dell’introduzione delle validation, queste restituiranno errori e potrebbero interrompere i frontend/client.
Guida alla migrazione
È possibile utilizzare lo strumento di migrazione CLI per trovare eventuali problemi nelle operazioni GraphQL e risolverli. In alternativa, è possibile aggiornare l’endpoint del client GraphQL per utilizzare l’endpoint https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME
. Testare le query con questo endpoint vi aiuterà a trovare i problemi nelle vostre query.
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.
Strumento CLI di migrazione
La maggior parte degli errori delle operazioni GraphQL può essere individuata in anticipo nella propria codebase.
Per questo motivo, forniamo un’esperienza agevole per la validating delle operazioni GraphQL durante lo sviluppo o in CI.
@graphql-validate/cli
è un semplice strumento CLI che aiuta a validare le operazioni GraphQL rispetto a un determinato schema.
Per cominciare
Lo strumento può essere eseguito nel modo seguente:
1npx @graphql-validate/cli -s https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME -o *.graphql
Note:
- Impostare o sostituire $GITHUB_USER, $SUBGRAPH_NAME con i valori appropriati. Ad esempio:
artblocks/art-blocks
- L’URL dello schema di anteprima (https://api-next.thegraph.com/) fornito è fortemente limitato e verrà abbandonato una volta che tutti gli utenti saranno migrati alla nuova versione. Non usarlo in produzione.
- Le operazioni sono identificate in file con le seguenti estensioni
.graphql
,.ts
,.tsx
,.js
,jsx
(opzione-o
).
Output CLI
Lo strumento [@graphql-validate/cli](https://github.com/saihaj/graphql-validate)
CLI mostrerà gli errori delle operazioni GraphQL come segue:

Per ogni errore sono disponibili una descrizione, il percorso e la posizione del file e un link a un esempio di soluzione (vedere la sezione seguente).
Eseguire le query locali sullo schema di anteprima
Forniamo un endpoint https://api-next.thegraph.com/
che esegue una versione di graph-node
con le validation attivate.
È possibile provare le query inviandole a:
https://api-next.thegraph.com/subgraphs/id/<Qm...>
oppure
https://api-next.thegraph.com/subgraphs/name/<GITHUB_USER>/<SUBGRAPH_NAME>
Per lavorare sulle query che sono state contrassegnate da errori di validazione, si può usare il proprio strumento preferito di query GraphQL, come Altair o GraphiQL, e provare la query. Questi strumenti segnaleranno gli errori nella loro interfaccia utente, anche prima dell’esecuzione.
Come risolvere i problemi
Di seguito sono riportati tutti gli errori di validation GraphQL che potrebbero verificarsi nelle operazioni GraphQL esistenti.
Le variabili, le operazioni, i frammenti o gli argomenti di GraphQL devono essere unici
Abbiamo applicato regole per garantire che un’operazione includa un set unico di variabili GraphQL, operazioni, frammenti e argomenti.
Un’operazione GraphQL è valida solo se non contiene alcuna ambiguità.
A tal fine, è necessario garantire che alcuni componenti dell’operazione GraphQL siano unici.
Ecco un esempio di alcune operazioni non valide che violano queste regole:
Nome della query duplicato (#UniqueOperationNamesRule)
1# La seguente operazione ha violato la regola UniqueOperationName2# la regola UniqueOperationName poiché abbiamo una singola operazione con 2 query3# con lo stesso nome4query myData {5 id6}78query myData {9 name10}
Soluzione:
1query myData {2 id3}45query myData2 {6 # rinominare la seconda query7 name8}
Nome del frammento duplicato (#UniqueFragmentNamesRule)
1# L'operazione seguente ha violato2# la regola UniqueFragmentName.3query myData {4 id5 ...MyFields6}78fragment MyFields {9 metadata10}1112fragment MyFields {13 name14}
Soluzione:
1query myData {2 id3 ...MyFieldsName4 ...MyFieldsMetadata5}67fragment MyFieldsMetadata { # assegna un nome unico al frammento8 metadati9}1011fragment MyFieldsName { # assegna un nome unico al frammento12 nome13}
Nome variabile duplicato (#UniqueVariableNamesRule)
1# L'operazione seguente viola la norma UniqueVariables.2query myData($id: String, $id: Int) {3 id4 ...MyFields5}
Soluzione:
1query myData($id: String) {2 # mantiene la variabile rilevante (qui: `$id: String`)3 id4 ...MyFields5}
Nome dell’argomento duplicato (#UniqueArgument)
1# L'operazione seguente ha violato la norma UniqueArguments2query myData($id: ID!) {3 userById(id: $id, id: "1") {4 id5 }6}
Soluzione:
1query myData($id: ID!) {2 userById(id: $id) {3 id4 }5}
Duplicazione della query anonima (#LoneAnonymousOperationRule)
Inoltre, l’uso di due operazioni anonime violerà la norma LoneAnonymousOperation
, a causa di un conflitto nella struttura della risposta:
1# Questa operazione fallirà se eseguita insieme in2# un'unica operazione con le due query seguenti:3query {4 someField5}67query {8 otherField9}
Soluzione:
1query {2 someField3 otherField4}
Oppure dare un nome alle due query:
1query FirstQuery {2 someField3}45query SecondQuery {6 otherField7}
Campi sovrapposti
Un set di selezione GraphQL è considerato valido solo se risolve correttamente l’eventuale set di risultati.
Se uno specifico set di selezione, o un campo, crea ambiguità sia per il campo selezionato che per gli argomenti utilizzati, il servizio GraphQL non riuscirà a validare l’operazione.
Ecco alcuni esempi di operazioni non valide che violano questa regola:
Alias di campi in conflitto (#OverlappingFieldsCanBeMergedRule)
1# L'aliasing dei campi potrebbe causare conflitti, sia con2# altri alias o con altri campi che esistono nello3# schema GraphQL.4query {5 dogs {6 name: nickname7 name8 }9}
Soluzione:
1query {2 dogs {3 name: nickname4 originalName: name # alias the original `name` field5 }6}
Campi in conflitto con gli argomenti (#OverlappingFieldsCanBeMergedRule)
1# Argomenti diversi possono portare a dati diversi,2# quindi non possiamo presumere che i campi siano gli stessi.3query {4 dogs {5 doesKnowCommand(dogCommand: SIT)6 doesKnowCommand(dogCommand: HEEL)7 }8}
Soluzione:
1query {2 dogs {3 knowsHowToSit: doesKnowCommand(dogCommand: SIT)4 knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)5 }6}
Inoltre, in casi d’uso più complessi, si potrebbe violare questa regola utilizzando due frammenti che potrebbero causare un conflitto nell’insieme atteso:
1query {2 # Alla fine, abbiamo due definizioni di "x", che puntano3 # a campi diversi!4 ...A5 ...B6}78fragment A on Type {9 x: a10}1112fragment B on Type {13 x: b14}
Inoltre, le direttive GraphQL lato client come @skip
e @include
potrebbero portare ad ambiguità, ad esempio:
1fragment mergeSameFieldsWithSameDirectives on Dog {2 name @include(if: true)3 name @include(if: false)4}
Per saperne di più sull’algoritmo, consultare qui.
Variabili o frammenti non utilizzati
Un’operazione GraphQL è considerata valida solo se vengono utilizzati tutti i componenti definiti dall’operazione (variabili, frammenti).
Ecco alcuni esempi di operazioni GraphQL che violano queste regole:
Variabile inutilizzata (#NoUnusedVariablesRule)
1# Non valido, perché $someVar non viene mai utilizzato.2query something($someVar: String) {3 someData4}
Soluzione:
1query something {2 someData3}
Frammento non utilizzato (#NoUnusedFragmentsRule)
1# Non valido, perché il frammento AllFields non viene mai utilizzato.2query something {3 someData4}56fragment AllFields { # unused :(7 name8 age9}
Soluzione:
1# Non valido, perché il frammento AllFields non viene mai utilizzato.2query something {3 someData4}56# rimuovere il frammento `AllFields`
Set di selezione non valido o mancante (#ScalarLeafsRule)
Inoltre, la selezione di un campo GraphQL è valida solo se il seguente è validato:
- Un campo oggetto deve avere un set di selezione specificato.
- Un campo bordo (scalare, enum) non deve avere un set di selezione specificato.
Ecco alcuni esempi di violazione di queste regole con il seguente schema:
1type Image {2 url: String!3}45type User {6 id: ID!7 avatar: Image!8}910type Query {11 user: User!12}
Set di selezione non valido
1query {2 user {3 id { # Invalid, because "id" is of type ID and does not have sub-fields45 }6 }7}
Soluzione:
1query {2 user {3 id4 }5}
Set di selezione mancante
1query {2 user {3 id4 image # `image` requires a Selection-Set for sub-fields!5 }6}
Soluzione:
1query {2 user {3 id4 image {5 src6 }7 }8}
Valori degli argomenti non corretti (#VariablesInAllowedPositionRule)
Le operazioni GraphQL che passano valori codificati agli argomenti devono essere validi, in base al valore definito nello schema.
Ecco alcuni esempi di operazioni non valide che violano queste regole:
1scopi della query {2 # Se "name" è definito come "String" nello schema,3 # questa query fallirà durante la validazione.4 purpose(name: 1) {5 id6 }7}89# Questo può accadere anche quando viene definita una variabile non corretta:1011scopi della query ($name: Int!) {12 # Se "name" è definito come `String` nello schema,13 # questa query fallirà durante la validazione, perché la14 # variabile utilizzata è di tipo `Int`.15 purpose(name: $name) {16 id17 }18}
Tipo, variabile, frammento o direttiva sconosciuti (#UnknownX)
L’API GraphQL solleverà un errore se viene utilizzato un tipo, una variabile, un frammento o una direttiva sconosciuti.
Questi riferimenti sconosciuti devono essere corretti:
- rinominare se si tratta di un errore di battitura
- altrimenti, rimuovere
Frammento: diffusione o definizione non valida
Diffusione del frammento non valida (#PossibleFragmentSpreadsRule)
Un frammento non può essere distribuito su un tipo non applicabile.
Ad esempio, non si può applicare un frammento Cat
al tipo Dog
:
1query {2 dog {3 ...CatSimple4 }5}67fragment CatSimple on Cat {8 # ...9}
Definizione di frammento non valida (#FragmentsOnCompositeTypesRule)
Tutti i frammenti devono essere definiti su (usando on ...
) un tipo composito, in breve: oggetto, interfaccia o unione.
Gli esempi seguenti non sono validi, poiché la definizione di frammenti su scalari non è valida.
1fragment fragOnScalar on Int {2 # non possiamo definire un frammento su uno scalare (`Int`)3 something4}56fragment inlineFragOnScalar on Dog {7 ... on Boolean {8 # `Boolean` non è un subtipo di `Dog`9 somethingElse10 }11}
Utilizzo delle direttive
La direttiva non può essere utilizzata in questa sede (#KnownDirectivesRule)
È possibile utilizzare solo le direttive GraphQL (@...
) supportate da Graph API.
Ecco un esempio con le direttive supportate da GraphQL:
1query {2 dog {3 name @include(true)4 age @skip(true)5 }6}
Nota: @stream
, @live
, @defer
non sono supportati.
La direttiva può essere utilizzata una sola volta in questo luogo (#UniqueDirectivesPerLocationRule)
Le direttive supportate da The Graph possono essere utilizzate una sola volta per ogni posizione.
Il seguente non è valido (e ridondante):
1query {2 dog {3 name @include(true) @include(true)4 }5}