Tutorial paso a paso para construir una API GraphQL con Apollo Server y Node.js
Aprender a construir una API GraphQL es una habilidad cada vez más demandada en el desarrollo backend. En este tutorial, te guiaré paso a paso para que puedas crear tu propia API GraphQL utilizando Apollo Server y Node.js, integrando una base de datos MongoDB para gestionar datos persistentemente.
Este tutorial está pensado para desarrolladores principiantes e intermedios que quieren consolidar sus conocimientos en desarrollo backend y entender cómo funciona una API GraphQL para principiantes.
Contenido
- Preparación del entorno
- Definición del esquema GraphQL
- Creación de resolvers para consultas y mutaciones
- Integración con MongoDB
- Pruebas básicas de la API
- Conclusión y buenas prácticas
Preparación del entorno
Paso 1: Instalar Node.js
Antes de comenzar, asegúrate de tener instalado Node.js en tu equipo. Puedes descargarlo desde https://nodejs.org/.
Verifica la instalación con los comandos:
1 2 3 |
node -v npm -v |
Paso 2: Crear un nuevo proyecto
Abre tu terminal o consola y crea una carpeta para el proyecto, luego inicializa con npm:
1 2 3 4 |
mkdir graphql-apollo-server cd graphql-apollo-server npm init -y |
Paso 3: Instalar las dependencias necesarias
Necesitaremos instalar Apollo Server, GraphQL, y algunas otras librerías:
1 2 |
npm install apollo-server graphql mongoose dotenv |
- apollo-server: servidor GraphQL que facilite configurar rápidamente.
- graphql: biblioteca para construir esquemas y ejecutar queries.
- mongoose: ODM para conectar y manipular MongoDB.
- dotenv: para manejar variables de entorno.
Definición del esquema GraphQL
El esquema define los tipos y las operaciones disponibles en nuestra API.
Paso 4: Crear el archivo principal
Crea un archivo llamado index.js
en la raíz del proyecto.
Paso 5: Definir tipos y esquemas
Vamos a definir un esquema sencillo para manejar un recurso “Book” (libro), con propiedades básicas
como id
, title
y author
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
const { ApolloServer, gql } = require('apollo-server'); // Definimos el esquema GraphQL con typedefs usando gql const typeDefs = gql` type Book { id: ID! title: String! author: String! } type Query { books: [Book]! book(id: ID!): Book } type Mutation { addBook(title: String!, author: String!): Book updateBook(id: ID!, title: String, author: String): Book deleteBook(id: ID!): Boolean } `; |
Explicación:
Book
es el tipo principal con campos.Query
para obtener libros, uno o muchos.Mutation
para crear, actualizar y eliminar librerías.
Creación de resolvers para consultas y mutaciones
Los resolvers contienen la lógica para ejecutar las operaciones declaradas en los tipos.
Paso 6: Crear resolvers básicos de ejemplo
Para empezar, vamos a probar algunos datos estáticos antes de conectar con la base de datos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
let books = [ { id: '1', title: '1984', author: 'George Orwell' }, { id: '2', title: 'The Great Gatsby', author: 'F. Scott Fitzgerald' } ]; const resolvers = { Query: { books: () => books, book: (parent, args) => books.find(book => book.id === args.id), }, Mutation: { addBook: (parent, args) => { const newBook = { id: String(books.length + 1), title: args.title, author: args.author, }; books.push(newBook); return newBook; }, updateBook: (parent, args) => { const index = books.findIndex(book => book.id === args.id); if (index === -1) return null; books[index] = { ...books[index], title: args.title || books[index].title, author: args.author || books[index].author, }; return books[index]; }, deleteBook: (parent, args) => { const initialLength = books.length; books = books.filter(book => book.id !== args.id); return books.length < initialLength; } } }; |
Paso 7: Inicializar Apollo Server
Agrega la inicialización y arranque del servidor en index.js
:
1 2 3 4 5 6 |
const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); |
Ahora puedes ejecutar la API con:
1 2 |
node index.js |
Y visitar la URL que aparece en consola para probar queries y mutaciones con la interfaz gráfica de Apollo Server.
Integración con MongoDB
Para manejar datos reales, conectaremos MongoDB usando Mongoose.
Paso 8: Configurar MongoDB
Puedes usar MongoDB Atlas para crear una base de datos gratuita en la nube o instalar MongoDB localmente.
Luego crea un archivo .env
en la raíz para almacenar la conexión:
1 2 |
MONGO_URI=mongodb+srv://usuario:contraseña@cluster0.mongodb.net/miDB?retryWrites=true&w=majority |
Paso 9: Conectar la base de datos
Modifica index.js
para usar dotenv y conectar a MongoDB:
1 2 3 4 5 6 7 8 9 10 11 12 |
require('dotenv').config(); const mongoose = require('mongoose'); mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true }).then(() => { console.log('🔥 Conectado a MongoDB'); }).catch(err => { console.error('Error conectando a MongoDB:', err); }); |
Paso 10: Crear el modelo Mongoose
Crea un modelo para Book con mongoose:
1 2 3 4 5 6 7 |
const bookSchema = new mongoose.Schema({ title: String, author: String }); const Book = mongoose.model('Book', bookSchema); |
Paso 11: Actualizar resolvers para usarlos con MongoDB
Reemplaza los resolvers que usaban el arreglo books
por operaciones asincrónicas con Mongoose:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
const resolvers = { Query: { books: async () => await Book.find(), book: async (parent, args) => await Book.findById(args.id), }, Mutation: { addBook: async (parent, args) => { const newBook = new Book({ title: args.title, author: args.author }); return await newBook.save(); }, updateBook: async (parent, args) => { return await Book.findByIdAndUpdate( args.id, { $set: { ...(args.title && { title: args.title }), ...(args.author && { author: args.author }) } }, { new: true } // Retorna el documento actualizado ); }, deleteBook: async (parent, args) => { const result = await Book.findByIdAndDelete(args.id); return result ? true : false; } } }; |
Pruebas básicas de la API
Paso 12: Probar la API con Apollo Server Playground
Cuando ejecutes tu servidor (node index.js
), accede a la URL mostrada (usualmente http://localhost:4000
) y verás una interfaz para hacer consultas.
Aquí tienes ejemplos de operaciones:
- Consulta para obtener todos los libros
1 2 3 4 5 6 7 8 |
query GetBooks { books { id title author } } |
- Mutación para agregar un libro
1 2 3 4 5 6 7 8 |
mutation AddBook { addBook(title: "Clean Code", author: "Robert C. Martin") { id title author } } |
- Mutación para actualizar un libro
1 2 3 4 5 6 7 8 |
mutation UpdateBook { updateBook(id: "ID_DEL_LIBRO", title: "Código limpio") { id title author } } |
- Mutación para eliminar un libro
1 2 3 4 |
mutation DeleteBook { deleteBook(id: "ID_DEL_LIBRO") } |
Nota: Reemplaza ID_DEL_LIBRO
con el id real que obtengas en la consulta.
Paso 13: Herramientas adicionales
-
Puedes usar extensiones de navegador como Altair GraphQL Client o Insomnia para probar tu API.
-
También es buena práctica implementar pruebas automatizadas usando frameworks como Jest o Mocha, pero esto queda para otro tutorial.
Conclusión y buenas prácticas
¡Felicidades! Has construido una API GraphQL utilizando Apollo Server y Node.js, integrando una base de datos MongoDB. Este ejemplo básico es una excelente base para proyectos más complejos.
Buenas prácticas recomendadas:
- Organiza tu código: divide typedefs, resolvers y modelos en archivos independientes.
- Usa variables de entorno para credenciales (no las subas a repositorios).
- Implementa validaciones y manejo de errores en resolvers.
- Seguridad: añade autenticación y autorización en resolvers cuando sea necesario.
- Documenta tu API con descripciones en el esquema para aprovechar herramientas de introspección.
- Versiona tu API si piensas evolucionarla.
Qué seguir aprendiendo
- React y Apollo Client para el frontend.
- Testing unitario y de integración.
- DataLoader para optimizar resolvers.
- Subscriptions en GraphQL para actualizaciones en tiempo real.
Si encontraste útil este tutorial, te invito a compartirlo y seguir explorando el poder de GraphQL en tus proyectos backend.