Trabajar con directivas GraphQL integradas | Programar Plus

Directivas son una de las mejores características de GraphQL, y la más tácita.

Exploremos cómo trabajar con el esquema integrado y las directivas de operación de GraphQL que todas las API que cumplen con las especificaciones de GraphQL deben implementar. Son extremadamente útiles si está trabajando con un front-end dinámico porque tiene el control para reducir la carga útil de respuesta dependiendo de con qué esté interactuando el usuario.

Una descripción general de las directivas

Imaginemos una aplicación en la que tiene la opción de personalizar las columnas que se muestran en una tabla. Si oculta dos o tres columnas, entonces realmente no es necesario buscar los datos para esas celdas. Sin embargo, con las directivas GraphQL, podemos elegir incluir u omitir esos campos.

La especificación GraphQL define qué son las directivas y la ubicación donde se pueden usar. Específicamente, las operaciones del consumidor (como una consulta) y el propio esquema subyacente pueden utilizar las directivas. O, en términos simples, las directivas se basan en un esquema o en una operación. Directivas de esquema se utilizan cuando se genera el esquema, y directivas de operación ejecutar cuando se ejecuta una consulta.

En resumen, las directivas se pueden usar para fines de metadatos, sugerencias de tiempo de ejecución, análisis de tiempo de ejecución (como devolver fechas en un formato específico) y descripciones extendidas (como obsoletas).

Cuatro tipos de directivas

GraphQL cuenta con cuatro directivas principales tal como se definen en el borrador de trabajo de la especificación, y una de ellas no se ha publicado como borrador de trabajo.

  • @include
  • @skip
  • @deprecated
  • @specifiedBy (borrador de trabajo)

Si sigue de cerca GraphQL, también notará que dos directivas adicionales se fusionaron con la implementación de JavaScript que puede probar hoy: @stream y @defer. Estos no son parte de la especificación oficial por el momento, mientras que la comunidad los prueba en aplicaciones del mundo real.

@include

El @include La directiva, fiel a su nombre, nos permite condicionar campos de inclusión pasando un if argumento. Dado que es condicional, tiene sentido usar una variable en la consulta para verificar la veracidad.

Por ejemplo, si la variable en los siguientes ejemplos es veraz, entonces el name El campo se incluirá en la respuesta a la consulta.

query getUsers($showName: Boolean) {
  users {
    id
    name @include(if: $showName)
  }
}

Por el contrario, podemos optar por no incluir el campo pasando la variable $showName como false junto con la consulta. También podemos especificar un valor predeterminado para el $showName variable, por lo que no es necesario pasarla con cada solicitud:

query getUsers($showName: Boolean = true) {
  users {
    id
    name @include(if: $showName)
  }
}

@skip

Podemos expresar el mismo tipo de cosas con lo que acabamos de hacer, pero usando @skip directiva en su lugar. Si el valor es verdadero, entonces, como era de esperar, omitirá ese campo.

query getUsers($hideName: Boolean) {
  users {
    id
    name @skip(if: $hideName)
  }
}

Si bien esto funciona muy bien para campos individuales, es posible que en ocasiones deseemos incluir u omitir más de un campo. Podríamos duplicar el uso de @include y @skip a través de múltiples líneas como esta:

query getUsers($includeFields: Boolean) {
  users {
    id
    name @include(if: $includeFields)
    email @include(if: $includeFields)
    role @include(if: $includeFields)
  }
}

Ambos @skip y @include Las directivas se pueden usar en campos, extensiones de fragmentos y fragmentos en línea, lo que significa que podemos hacer otra cosa, como esta en su lugar, con fragmentos en línea:

query getUsers($excludeFields: Boolean) {
  users {
    id
    ... on User @skip(if: $excludeFields) {
      name
      email
      role
    }
  }
}

Si un fragmento ya está definido, también podemos usar @skip y @include cuando difundimos un fragmento en la consulta:

fragment User on User {
  name
  email
  role
}

query getUsers($excludeFields: Boolean) {
  users {
    id
    ...User @skip(if: $excludeFields)
  }
}

@deprecated

El @deprecated La directiva aparece solo en el esquema y no es algo que un usuario proporcionaría como parte de una consulta como la que hemos visto anteriormente. En cambio, el @deprecated La directiva la especifica el desarrollador que mantiene el esquema de la API GraphQL.

Como usuario, si intentamos recuperar un campo que ha quedado obsoleto en el esquema, recibiremos una advertencia como esta que proporciona ayuda contextual.

Un ejemplo ampliado de una consulta GraphQL resaltada por sintaxis para getUsers, que contiene un objeto de usuario con propiedades de identificación y título.  La propiedad del título está subrayada en amarillo con una información sobre herramientas contextual abierta debajo de ella que muestra una advertencia en amarillo y blanco que sugiere usar el campo de nombre en su lugar.En este ejemplo, el campo de título se ha marcado como obsoleto y la directiva proporciona una sugerencia útil para reemplazarlo.

Para marcar un campo como obsoleto, necesitamos usar el @deprecated directiva dentro del lenguaje de definición de esquema (SDL), pasando una reason dentro de los argumentos, así:

type User {
  id: ID!
  title: String @deprecated(reason: "Use name instead")
  name: String!
  email: String!
  role: Role
}

Si emparejamos esto con el @include directiva, podríamos obtener condicionalmente el campo obsoleto en función de una variable de consulta:

fragment User on User {
  title @include(if: $includeDeprecatedFields)
  name
  email
  role
}

query getUsers($includeDeprecatedFields: Boolean! = false) {
  users {
    id
    ...User
  }
}

@specifiedBy

@specifiedBy es la cuarta de las directivas y actualmente forma parte del borrador de trabajo. Está configurado para ser utilizado por implementaciones escalares personalizadas y tomar un url argumento que debe apuntar a una especificación para el escalar.

Por ejemplo, si agregamos un escalar personalizado para la dirección de correo electrónico, querremos pasar la URL a la especificación de la expresión regular que usamos como parte de eso. Usando el último ejemplo y la propuesta definida en RFC # 822, un escalar para EmailAddress se definiría en el esquema así:

scalar EmailAddress @specifiedBy(url: "https://www.w3.org/Protocols/rfc822/")

Se recomienda que las directivas personalizadas tengan un nombre con prefijo para evitar colisiones con otras directivas agregadas. Si está buscando un ejemplo de directiva personalizada y cómo se crea, eche un vistazo a GraphQL Public Schema. Es una directiva GraphQL personalizada que tiene compatibilidad tanto con el código como con el esquema para anotar qué API se puede consumir en público.

Terminando

Así que esa es una mirada de alto nivel a las directivas GraphQL. Nuevamente, creo que las directivas son una especie de héroe olvidado que queda eclipsado por otras características de GraphQL. Ya tenemos mucho control con el esquema GraphQL y las directivas nos brindan un control aún más detallado para obtener exactamente lo que queremos de las consultas. Ese es el tipo de eficiencia y eso hace que la API GraphQL sea tan rápida y, en última instancia, más amigable para trabajar.

Y si está creando una API GraphQL, asegúrese de incluir estas directivas en la consulta de introspección. Tenerlas allí no solo les brinda a los desarrolladores el beneficio de un control adicional, sino una mejor experiencia general para los desarrolladores. Piense en lo útil que sería si @deprecate campos para que los desarrolladores sepan qué hacer sin tener que dejar el código? Eso es poderoso en sí mismo.

Gráfico de encabezado cortesía de Isabel Gonçalves en Unsplash