¿Cómo crear un backend con GraphQL?

En este artículo te enseñaré a crear un backend con Nodejs usando GraphQL y Apollo Server.

Diseño web
6 minutos
Hace 5 años
¿Cómo crear un backend con GraphQL?

¡Accede a cientos de cursos
con solo un pago al año!

Blog Microbanner

En el artículo de introducción a GraphQL te expliqué los conceptos fundamentales sobre esta tecnología y hoy te enseñaré a crear un backend con Nodejs. Para este fin usaremos:

Para empezar nuestro proyecto tenemos que instalar Apollo Server y graphql:

1npm i apollo-server graphql 2

Definiendo nuestro esquema de GraphQL

Creamos el archivo typeDefs.js y definimos nuestro esquema, (queries, mutaciones y tipo)

1const { gql } = require('apollo-server'); 2 3const typeDefs = gql` 4 type Task { 5 id: Int! 6 name: String! 7 description: String! 8 completed: Boolean! 9 } 10 11 type Query { 12 tasks: [Task]! 13 task(id: Int!): Task 14 } 15 16 type Mutation { 17 addTask( 18 name: String!, 19 description: String!, 20 completed: Boolean! 21 ): Task! 22 } 23`; 24 25module.exports = typeDefs; 26

Usamos gql para definir un esquema de GraphQL, en este hay tres componentes principales:

  • Task. Dentro del cual definimos los campos id, name, description y completed.
  • Las queries que soportará nuestro servicio. Son tasks y task, estas consiguen una lista de tareas y una tarea en específico dado su id.
  • Mutaciones:addTask que recibirá los argumentos name, description y completed y a su vez retornará una tarea.

Al final exportamos la definición de nuestro esquema.

Definiendo nuestros resolvers

Los resolvers son las funciones que satisfacen las queries y mutaciones. Es en los resolvers donde estaremos implementando la lógica para conseguir y agregar las tareas. Para hacerlo crearemos un archivo llamado resolvers.js:

1const tasks = []; 2 3module.exports = { 4 Query: { 5 tasks: (parent, args, context) => tasks, 6 task: (parent, args, context) => { 7 const task = tasks.find((task) => task.id === args.id); 8 return task; 9 }, 10 }, 11 Mutation: { 12 addTask: (parent, args, context) => { 13 const newTask = { 14 id: tasks.length, 15 name: args.name, 16 description: args.description, 17 completed: args.completed, 18 }; 19 20 tasks.push(newTask); 21 return newTask; 22 }, 23 }, 24}; 25

En este archivo definimos un array tasks que usaremos como fuente de datos en nuestra aplicación.

Ten presente que GraphQL es independiente de la base o fuente de datos que estemos usando. Puedes usar bases de datos como mongo o bases de datos SQL, incluso puedes obtener la información a través de otras apis.

Después de creado el array, exportaremos un objeto que tendrá las propiedades Query y Mutation

Query

1 Query: { 2 tasks: (parent, args, context) => tasks, 3 task: (parent, args, context) => { 4 const task = tasks.find((task) => task.id === args.id); 5 return task; 6 }, 7 }, 8

Aquí es donde estarán definidas todos los resolvers para devolver la información en las queries que nos hagan nuestros clientes. Las funciones dentro de la propiedad Query deben llamarse igual a la query que van a satisfacer.

En nuestro esquema definimos la query tasks así que en la propiedad Query de nuestros resolvers crearemos la propiedad tasks, que tendrá la función que nos devuelve las tareas cuando alguno de nuestros clientes haga alguna query a tasks.

Luego definimos otro resolver para la query de task y en esta función usamos los parámetros que nos provee apollo para todos nuestros resolvers (parent, args y context ). Para más información acerca de estos parámetros los invito a leer este artículo en la documentación de apollo. En el caso del resolver para task solo haremos uso del parámetro args, en este nos llegará el argumento id que se definió en la query task de nuestro esquema:

1// En nuestro esquema definimos que en esta query ibamos a recibir un campo id de tipo Int 2// Y que devolveriamos una tarea 3task(id: Int!): Task 4

Lo que hace args es reunir esos argumentos definidos en nuestro esquema en un objeto que es lo que representa args y con el valor que se le pase a id buscamos en nuestra lista de tareas alguna que tenga el mismo id y lo retornamos, este retorno es el que dará la respuesta a la petición del cliente.

Mutation

1Mutation: { 2 addTask: (parent, args, context) => { 3 const newTask = { 4 id: tasks.length, 5 name: args.name, 6 description: args.description, 7 completed: args.completed, 8 }; 9 10 tasks.push(newTask); 11 return newTask; 12 }, 13 }, 14

Solo nos queda nuestra mutación para agregar una nueva tarea, esta debe ubicarse dentro de la propiedad Mutation y al igual que en las queries debe de llamarse igual a la mutación definida en nuestro esquema que espera satisfacer. Aquí también recibimos en args los argumentos name, description y completed (así está definido en el esquema). Con estos campos formamos el objeto que agregaremos en el array y lo retornamos, es muy importante que este objeto cumpla con la estructura definida en el type Task, en caso contrario tendríamos errores.

Levantar el servidor GraphQL

para eso tenemos el siguiente código en el archivo index.js:

1const { ApolloServer } = require('apollo-server'); 2const typeDefs = require('./typeDefs'); 3const resolvers = require('./resolvers'); 4 5const server = new ApolloServer({ 6 typeDefs, 7 resolvers, 8 playground: true, 9}); 10 11server.listen().then(() => { 12 console.log('Corriendo aplicación graphQL en <http://localhost:4000/grapqhql>'); 13}); 14
  • Aquí importamos la definición de nuestro esquema y nuestros resolvers y los usamos para construir una instancia de ApolloServer,
  • Además ponemos la propiedad playground en true que permite tener un entorno gráfico donde interactuaremos con el servidor.
  • Y para levantar el servidor usamos la función listen().

Si abrimos http://localhost:4000/grapqhql podremos ver lo siguiente:

servidor

Este playground que nos da apollo nos servirá para probar nuestro servicio, por ejemplo: ejecutamos la mutación addTask para agregar una tarea al array.

playground

Al lado izquierdo escribimos nuestra mutación pasándole los argumentos que nos pide para crear la tarea y diciéndole que de la tarea resultante queremos conseguir el id y el nombre. Al darle click al botón de play conseguiremos como respuesta lo que tenemos a la derecha, donde podemos ver solamente el id y el nombre como lo indiqué cuando escribí la mutación.

Ahora veamos la query de tasks:

tasks

Como ves estoy usando la query de tasks, está como la definimos en el esquema, nos retorna un array con todas las tareas, en este caso solo retorna la que acabamos de crear y con los campos que le especifiqué: id, name y description.

Al igual podemos probar la query task:

task

Aquí usamos la query task buscando una tarea por un id en especial, 0 en este caso, al lado derecho recibimos un único objeto task con los campos id, name y completed como lo definí al momento de hacer la query.

Eso es todo, espero que te haya gustado este artículo. Si quieres ver el código, te dejo el repositorio con todo lo que hicimos. Próximamente te enseñaré a consumir este servicio desde frontend con vanilla js y React. ¡Hasta pronto!

Comentarios de los usuarios