En GraphQL, los tipos escalares son los tipos de datos más básicos que representan valores atómicos como Int
, Float
, String
, Boolean
y ID
. Sin embargo, en muchas aplicaciones, es posible que necesitemos tipos de datos más específicos que no están cubiertos por estos tipos escalares predeterminados. Aquí es donde entran en juego los escalares personalizados.
¿Qué son los Escalares Personalizados?
Los escalares personalizados en GraphQL permiten definir tipos de datos específicos que se ajustan a las necesidades de tu aplicación. Por ejemplo, podrías necesitar un tipo de dato para representar una fecha, una URL, o un correo electrónico. Los escalares personalizados te permiten definir estos tipos y especificar cómo deben ser serializados, deserializados y validados.
Definición de un Escalar Personalizado
Para definir un escalar personalizado, necesitas:
- Definir el tipo escalar en tu esquema GraphQL.
- Implementar las funciones de serialización, deserialización y validación.
Paso 1: Definir el Tipo Escalar en el Esquema
Primero, define el tipo escalar en tu esquema GraphQL. Por ejemplo, si deseas crear un tipo escalar para representar una fecha, podrías definirlo así:
Paso 2: Implementar las Funciones de Serialización, Deserialización y Validación
Luego, necesitas implementar las funciones que manejarán la lógica de este tipo escalar. Aquí hay un ejemplo en JavaScript utilizando graphql-js
:
const { GraphQLScalarType, Kind } = require('graphql'); const DateScalar = new GraphQLScalarType({ name: 'Date', description: 'A custom scalar type for dates', serialize(value) { // Serialización: Convierte el valor a un formato que pueda ser enviado al cliente return value instanceof Date ? value.toISOString() : null; }, parseValue(value) { // Deserialización: Convierte el valor recibido del cliente a un formato que pueda ser usado en el servidor return new Date(value); }, parseLiteral(ast) { // Validación: Verifica que el valor recibido es del tipo esperado if (ast.kind === Kind.STRING) { return new Date(ast.value); } return null; } }); module.exports = DateScalar;
En este ejemplo:
serialize
: Convierte el valor de una fecha a una cadena ISO 8601 para enviarla al cliente.parseValue
: Convierte una cadena ISO 8601 recibida del cliente a un objetoDate
.parseLiteral
: Verifica que el valor recibido es una cadena y lo convierte a un objetoDate
.
Uso del Escalar Personalizado en el Esquema
Una vez que has definido e implementado tu escalar personalizado, puedes usarlo en tu esquema GraphQL como cualquier otro tipo:
Ejemplo Completo
A continuación, se muestra un ejemplo completo de cómo definir y usar un escalar personalizado en un servidor GraphQL utilizando graphql-js
y express
:
Definición del Esquema
const { ApolloServer, gql } = require('apollo-server'); const DateScalar = require('./DateScalar'); // Importa tu escalar personalizado const typeDefs = gql` scalar Date type Event { id: ID! name: String! date: Date! } type Query { events: [Event] } `; const resolvers = { Date: DateScalar, // Asocia el escalar personalizado con el tipo en el esquema Query: { events: () => [ { id: '1', name: 'GraphQL Conference', date: new Date() }, { id: '2', name: 'JavaScript Meetup', date: new Date() } ] } }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Ejercicio Práctico
Ejercicio: Crear un Escalar Personalizado para URLs
- Define un tipo escalar
URL
en tu esquema. - Implementa las funciones de serialización, deserialización y validación para el tipo
URL
. - Usa el tipo
URL
en un tipoLink
que tenga camposid
,description
yurl
.
Solución:
const { GraphQLScalarType, Kind } = require('graphql'); const URLScalar = new GraphQLScalarType({ name: 'URL', description: 'A custom scalar type for URLs', serialize(value) { try { return new URL(value).toString(); } catch (e) { throw new Error('Invalid URL'); } }, parseValue(value) { try { return new URL(value).toString(); } catch (e) { throw new Error('Invalid URL'); } }, parseLiteral(ast) { if (ast.kind === Kind.STRING) { try { return new URL(ast.value).toString(); } catch (e) { throw new Error('Invalid URL'); } } return null; } }); const typeDefs = gql` scalar URL type Link { id: ID! description: String! url: URL! } type Query { links: [Link] } `; const resolvers = { URL: URLScalar, Query: { links: () => [ { id: '1', description: 'GraphQL Official Site', url: 'https://graphql.org' }, { id: '2', description: 'Apollo GraphQL', url: 'https://www.apollographql.com' } ] } }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); });
Conclusión
Los escalares personalizados en GraphQL te permiten definir tipos de datos específicos que se ajustan a las necesidades de tu aplicación. Al implementar funciones de serialización, deserialización y validación, puedes asegurarte de que los datos se manejan correctamente tanto en el cliente como en el servidor. Con esta capacidad, puedes extender GraphQL para manejar una amplia variedad de tipos de datos personalizados, mejorando la flexibilidad y robustez de tus APIs.
Curso de GraphQL
Módulo 1: Introducción a GraphQL
- ¿Qué es GraphQL?
- GraphQL vs REST
- Configuración de un Servidor GraphQL
- Conceptos Básicos del Esquema de GraphQL
Módulo 2: Conceptos Fundamentales
Módulo 3: Diseño Avanzado de Esquemas
Módulo 4: Trabajando con Datos
Módulo 5: Rendimiento y Seguridad
Módulo 6: Herramientas y Ecosistema
Módulo 7: Pruebas y Despliegue
- Pruebas Unitarias de Resolvers
- Pruebas de Integración
- Integración Continua
- Despliegue de Servidores GraphQL