Contenido del curso
Fundamentos de GraphQL
Tipado en GraphQL
GraphQL en la Tienda con Express.js
- 11

Cómo separar resolvers GraphQL por entidad
Viendo ahora - 12

Conexión de Base de Datos y Consultas en GraphQL con SQLite
07:30 min - 13

Creación de productos con mutations e inputs en GraphQL
11:19 min - 14

Uso de Variables y Alias en GradQL para Optimizar Consultas
10:57 min - 15

Actualización y Eliminación de Productos con GraphQL
12:41 min - 16

Anidamiento de Entidades con GradQL en APIs
07:32 min
Autenticación con GraphQL y JSON Web Tokens
- 17

Autenticación de Usuarios con JWT en GraphQL y Node.js
18:01 min - 18

Creación de Mutación para Categorías con Validación de Roles
06:15 min - 19

Autenticación de JSON Web Tokens en GraphQL con Passport
08:07 min - 20

Validación de Roles y Sesiones con GradQL y Express
10:22 min - 21

Validación de Datos en GradQL con Scalars Personalizados
15:19 min
Bonus
Conclusiones
Cómo separar resolvers GraphQL por entidad
Resumen
Organizar resolvers en GraphQL por responsabilidad es una práctica que mejora la escalabilidad y el mantenimiento de tu API. Si los acumulas todos en un solo archivo, tarde o temprano vas a terminar con un monstruo difícil de leer. Aquí aprendes a dividirlos por dominio, igual que harías con las rutas en una Rest API.
¿Por qué dividir los resolvers en archivos separados?
Cuando creces una API con productos, categorías, órdenes y customers, tener todos los resolvers en un solo archivo rompe el principio de una sola responsabilidad. La idea es replicar lo que ya haces con tu routing en Rest: un archivo product.router se encarga solo de productos, otro de órdenes, otro de customers.
En GraphQL aplicas la misma lógica creando, por ejemplo, un archivo product.resolvers que agrupe todas las funciones relacionadas con la entidad producto: obtener uno, obtener varios, crear, actualizar, eliminar.
¿Qué es un resolver en GraphQL? Es la función que ejecuta la lógica detrás de una query o mutation. Recibe parámetros como el contexto y los argumentos enviados desde el cliente, y devuelve los datos que coinciden con el esquema.
¿Cómo crear un archivo de resolvers por entidad?
La estructura parte de un archivo dedicado por entidad. Dentro defines funciones tipo arrow function que representan cada operación.
¿Qué estructura tiene un archivo product.resolvers?
Dentro del archivo declaras cada función con su firma completa. Un resolver recibe un primer parámetro que normalmente se ignora y un segundo parámetro con los argumentos enviados desde la query.
getProduct: retorna un producto individual usando un id recibido por argumentos.getProducts: retorna una lista de productos, por ahora un array vacío hasta conectar con la capa de servicios.- Funciones futuras como agregar, actualizar o eliminar producto.
Al final del archivo usas module.exports para exponer las funciones que este módulo se encarga de manejar. Así, todo lo relacionado con producto queda aislado y mantenible.
¿Cómo se reciben los argumentos en un resolver?
Puedes acceder a los argumentos de dos formas. La clásica usa args.id, donde args es el segundo parámetro de la función. La más limpia usa destructuring directamente en la firma para extraer solo el campo que necesitas.
js const getProduct = (_, { id }) => { return product; };
Este patrón hace el código más legible porque sabes de un vistazo qué argumentos consume cada resolver.
¿Cómo unir los resolvers en un archivo central?
Para no recargar el index.js, creas un archivo resolvers.js que funciona como directorio principal. Ahí importas cada conjunto de funciones por entidad y las ensamblas en el objeto que GraphQL espera.
js const { getProduct, getProducts } = require('./product.resolvers');
module.exports = { Query: { product: getProduct, products: getProducts, }, };
Este archivo cumple el mismo papel que el index.js de las rutas en Rest: enruta hacia el módulo correcto sin contener la lógica.
¿Por qué el nombre del resolver debe coincidir con el del esquema? GraphQL hace match entre el campo declarado en el esquema y la clave del objeto de resolvers. Si tu esquema define
product, la clave enQuerydebe llamarseproduct, aunque la función interna se llamegetProduct.
¿Cómo nombrar queries siguiendo convenciones de GraphQL?
En la mayoría de servidores GraphQL no se usan nombres tipo getProduct o getProducts en el esquema. Se prefiere nombrar las queries con la entidad directamente, ya que el contexto deja claro que es una lectura.
product: para obtener un producto individual.productsoallProducts: para obtener la lista completa.- Ejemplo real: la API pública de Star Wars expone
allFilmspara listar películas.
En el esquema, product recibe un ID! obligatorio porque sin él no puedes ubicar el recurso. El retorno, en cambio, sí permite null, porque el id solicitado podría no existir en la base de datos.
graphql type Query { product(id: ID!): Product products: [Product!]! }
La notación [Product!]! indica que el array no puede ser null y tampoco puede contener elementos null en su interior.
¿Cómo probar los resolvers en el playground?
Una vez configurado el esquema y los resolvers, abres el playground y lanzas la query seleccionando los campos que necesitas del objeto retornado.
graphql query { product(id: "1") { id name } }
Si pasas un id distinto, ese valor llega como argumento al resolver. Para products, como retorna un array de objetos, también debes seleccionar atributos específicos como id y name. Por ahora el resolver devuelve un array vacío, hasta conectar con la capa de servicios que gestiona la base de datos.
Con esta separación tienes una arquitectura limpia donde cada archivo cumple una sola responsabilidad y tu index.js queda mínimo. ¿Cómo organizas tú los resolvers en tus proyectos? Cuéntalo en los comentarios.