Guía de migración de Validaciones GraphQL
Reading time: 8 min
Pronto graph-node
admitirá una cobertura del 100% de la .
Versiones anteriores de graph-node
no soportaban todas las validaciones y proporcionaban respuestas más gráciles, por lo que en casos de ambigüedad, graph-node
ignoraba componentes inválidos de operaciones GraphQL.
El soporte de Validaciones GraphQL es el pilar para las próximas nuevas características y el rendimiento a escala de The Graph Network.
También asegurará la determinismo de las respuestas de las consultas, un requisito clave en The Graph Network.
Habilitar las Validaciones GraphQL romperá algunas consultas existentes enviadas a la API de The Graph.
Para ser compatible con esas validaciones, por favor sigue la guía de migración.
⚠️ Si no migras tus consultas antes de que se implementen las validaciones, estas devolverán errores y podrían romper tus interfaces de usuario/clientes.
Puedes utilizar la herramienta de migración CLI para encontrar cualquier problema en tus operaciones GraphQL y solucionarlo. Alternativamente, puedes actualizar el endpoint de tu cliente GraphQL para usar el endpoint https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME
. Probar tus consultas contra este endpoint te ayudará a encontrar los problemas en tus consultas.
No todos los subgrafos deberán migrarse, si estás utilizando o , ya se aseguran de que tus consultas sean válidas.
La mayoría de los errores en las operaciones de GraphQL pueden ser encontrados en tu código previamente.
Por esta razón, brindamos una experiencia fluida para validar tus operaciones de GraphQL durante el desarrollo o en CI.
es una herramienta CLI simple que ayuda a validar operaciones de GraphQL contra un esquema dado.
Puedes ejecutar la herramienta de la siguiente manera:
npx @graphql-validate/cli -s https://api-next.thegraph.com/subgraphs/name/$GITHUB_USER/$SUBGRAPH_NAME -o *.graphql
Notas:
- Configura o reemplaza $GITHUB_USER, $SUBGRAPH_NAME con los valores apropiados. Por ejemplo:
- La URL del esquema de vista previa () proporcionada tiene una limitación de tasa alta y se descontinuará una vez que todos los usuarios se hayan migrado a la nueva versión. No lo uses en producción.
- Las operaciones se identifican en archivos con las siguientes extensiones (opción
-o
).
La herramienta de línea de comandos [@graphql-validate/cli](https://github.com/saihaj/graphql-validate)
mostrará cualquier error en las operaciones GraphQL de la siguiente manera:
Por cada error, encontrarás una descripción, una ruta de archivo y posición, y un enlace a un ejemplo de solución (ver la siguiente sección).
Proporcionamos un punto final https://api-next.thegraph.com/
que ejecuta una versión de graph-node
que tiene las validaciones activadas.
Puedes probar tus consultas enviándolas a:
https://api-next.thegraph.com/subgraphs/id
o
https://api-next.thegraph.com/subgraphs/name/<GITHUB_USER>/<SUBGRAPH_NAME>
Para trabajar en consultas que hayan sido identificadas como teniendo errores de validación, puedes usar tu herramienta de consulta GraphQL favorita, como Altair o , y probar tu consulta. Esas herramientas también marcarán esos errores en su interfaz de usuario, incluso antes de ejecutarlos.
A continuación, encontrará todos los posibles errores de validación de GraphQL que podrían ocurrir en sus operaciones de GraphQL existentes.
Aplicamos reglas para garantizar que una operación incluye un conjunto único de variables GraphQL, operaciones, fragmentos y argumentos.
Una operación GraphQL solo es válida si no contiene ninguna ambigüedad.
Para lograr eso, necesitamos asegurarnos de que algunos componentes en su operación de GraphQL sean únicos.
Aquí hay un ejemplo de algunas operaciones inválidas que violan estas reglas:
Nombre de consulta duplicado (#UniqueOperationNamesRule)
# La siguiente operación viola la regla UniqueOperationName,# ya que tenemos una sola operación con 2 consultas con el mismo nombrequery myData {id}query myData {name}
Solución:
query myData {id}query myData2 {# rename the second queryname}
Nombre de Fragmento Duplicado (#UniqueFragmentNamesRule)
# La siguiente operación violó la regla UniqueFragmentNamequery myData {id...MyFields}fragment MyFields {metadata}fragment MyFields {name}
Solución:
query myData {id...MyFieldsName...MyFieldsMetadata}fragment MyFieldsMetadata { # asignar un nombre único al fragmento metadatos}fragment MyFieldsName { #asigna un nombre único al fragment name}
Nombre de variable duplicado (#UniqueVariableNamesRule)
# La siguiente operación viola la regla UniqueVariablesquery myData($id: String, $id: Int) {id...MyFields}
Solución:
query myData($id: String) {# Manten la variable relevante (aquí: `$id: String`)id...MyFields}
Nombre de argumento duplicado (#UniqueArgument)
# La siguiente operacion, violó la consulta UniqueArgumentsmyData($id: ID!) {userById(id: $id, id: "1") {id}}
Solución:
query myData($id: ID!) {userById(id: $id) {id}}
Consulta anonima duplicada (#LoneAnonymousOperationRule)
Además, el uso de dos operaciones anónimas violará la regla LoneAnonymousOperation
debido al conflicto en la estructura de respuesta:
# Esto fallará si se ejecuta en conjunto en# una sola operación con las siguientes dos consultas:query {someField}query {otherField}
Solución:
query {someFieldotherField}
O nombra las dos consultas:
query FirstQuery {someField}query SecondQuery {otherField}
Un conjunto de selección de GraphQL se considera válido solo si resuelve correctamente el conjunto de resultados final.
Si un conjunto de selección específico o un campo crea ambigüedad ya sea por el campo seleccionado o por los argumentos utilizados, el servicio GraphQL no podrá validar la operación.
Aquí hay algunos ejemplos de operaciones inválidas que violan estas reglas:
Alias de campos en conflicto (#OverlappingFieldsCanBeMergedRule)
# Poner alias a los campos puede causar conflictos# ya sea con otros alias o con otros campos que existen en el esquema de GraphQL.query {dogs {name: nicknamename}}
Solución:
query {dogs {name: nicknameoriginalName: name # alias el original `name` field}}
Campos en conflicto con argumentos (#OverlappingFieldsCanBeMergedRule)
# Diferentes argumentos pueden llevar a diferentes datos,# asi que no podemos asumir que los capos serán los mismos.query {dogs {doesKnowCommand(dogCommand: SIT)doesKnowCommand(dogCommand: HEEL)}}
Solución:
query {dogs {knowsHowToSit: doesKnowCommand(dogCommand: SIT)knowsHowToHeel: doesKnowCommand(dogCommand: HEEL)}}
Además, en casos de uso más complejos, se puede violar esta regla al utilizar dos fragmentos que puedan causar un conflicto en el conjunto de resultados esperado:
query {# Eventualmente, tenemos dos "x" definiciones, apuntando# para diferentes campos!...A...B}fragment A on Type {x: a}fragment B on Type {x: b}
Además de eso, las directivas GraphQL del lado del cliente como @skip
y @include
podrían causar ambigüedad, por ejemplo:
fragment mergeSameFieldsWithSameDirectives on Dog {name @include(if: true)name @include(if: false)}
Una operación GraphQL también se considera válida solo si se utilizan todos los componentes definidos en la operación (variables, fragmentos).
Aquí hay algunos ejemplos de operaciones de GraphQL que violan estas reglas:
Variable no utilizada (#NoUnusedVariablesRule)
# Inválido, porque $someVar nunca se usa.consulta algo($someVar: String) {someData}
Solución:
query something {someData}
Fragmento no Utilizado (#NoUnusedFragmentsRule)
#Inválido, ya que el fragmento AllFields nunca se utiliza.query something {someData}fragment AllFields { # unused :(nameage}
Solución:
# Invalido, porque el fragmento AllFields nunca se utiliza.query something {someData}# elimina el fragmento `AllFields`
Además, una selección de campos GraphQL solo es válida si se valida lo siguiente:
- Un campo de objeto debe tener un conjunto de selección especificado.
- Un campo de borde (escalar, enum) no debe tener un conjunto de selección especificado.
Aquí hay algunos ejemplos de violaciones de estas reglas con el siguiente esquema:
type Image {url: String!}type User {id: ID!avatar: Image!}type Query {user: User!}
Conjunto de Selección Inválido
query {user {id { # Invalido, porque "id" es de tipo ID y no tiene sub-campos}}}
Solución:
query {user {id}}
Falta el Conjunto de Selección
query {user {idimage # 'image' requiere un conjunto de selección para subcampos!}}
Solución:
query {user {idimage {src}}}
Las operaciones de GraphQL que pasan valores codificados a los argumentos deben ser válidas, basadas en el valor definido en el esquema.
Aquí hay algunos ejemplos de operaciones inválidas que violan estas reglas:
query purposes {# si "name" esta definido como "String" en el esquema,# Esta consulta fallará durante la validación.purpose(name: 1) {id}}# Esto también puede suceder cuando se define una variable incorrecta:query purposes($name: Int!) {# si "name" esta definido como `String` en el esquema,# esta consulta fallara durante la validación, por que la# variable usada es de tipo `Int`purpose(name: $name) {id}}
La API de GraphQL generará un error si se utiliza algún tipo, variable, fragmento o directiva desconocido.
Esas referencias desconocidas deben ser corregidas:
- renombrar si fue un error tipográfico
- de lo contrario, elimina
Extensión de fragmento no válida (#PossibleFragmentSpreadsRule)
Un fragmento no puede ser aplicado en un tipo no correspondiente.
Por ejemplo, no podemos aplicar un fragmento Cat
al tipo Dog
:
query {dog {...CatSimple}}fragment CatSimple on Cat {# ...}
Definicion de fragento inválida (#FragmentsOnCompositeTypesRule)
Todos los fragmentos deben definirse en (usando on ...
) un tipo compuesto, en resumen: objeto, interfaz o unión.
Los siguientes ejemplos son inválidos, ya que definir fragmentos en escalares es inválido.
fragment fragOnScalar on Int {# no podemos definir un fragmento sobre un escalar(`Int`)something}fragment inlineFragOnScalar on Dog {... on Boolean {# `Boolean` no es un subtipo de `Dog`somethingElse}}
La directiva no puede ser utilizada en esta ubicación (#KnownDirectivesRule)
Solo las directivas GraphQL (@...
) soportadas por la API de The Graph pueden ser utilizadas.
Aqui hay un ejemplo con The GraphQL con las directivas soportadas:
query {dog {name @include(true)age @skip(true)}}
Note: @stream
, @live
, @defer
no son soportadas.
La directiva no puede ser utilizada en esta ubicación (#UniqueDirectivesPerLocationRule)
Los directivas soportados por The Graph solo se pueden usar una vez por ubicación.
La siguiente es inválida (y redundante):
query {dog {name @include(true)age @skip(true)}}