Hamburger Icon
Así de fácil es crear una API con Fastify, gracias a Grace Hopper

Así de fácil es crear una API con Fastify, gracias a Grace Hopper

Grace Brewster Murray Hopper nació en 1906 en Nueva York y se convirtió en una de las primeras programadoras de la historia de la informática.

Durante la Segunda Guerra Mundial, se unió a la Marina de los Estados Unidos y trabajó en el Harvard Mark I, el primer ordenador electromecánico de gran escala. Su contribución clave fue la creación del primer compilador, como ya sabes, ese programa que traduce el código de programación humano a lenguaje de máquina, en unos y ceros.

Este fue un paso de gigante que allanó el camino para el desarrollo de lenguajes de alto nivel como COBOL.

En aquellos días, la programación se realizaba mediante tarjetas perforadas y la depuración del código era una tarea tediosa y propensa a errores.

Grace Hopper luchó contra la noción de que la programación debía ser exclusivamente matemática, argumentando que debía ser más accesible y comprensible para las personas de todas las disciplinas.

Hoy en día, la programación ha avanzado de manera exponencial. Contamos con frameworks como Fastify que hacen que la creación de APIs sea más rápida y sencilla que nunca.

Y con bases de datos como MongoDB, el almacenamiento y la recuperación de datos se han vuelto muy eficientes. Todo esto, gracias a los esfuerzos pioneros de programadores como Grace, que sentaron las bases de lo que hoy conocemos como desarrollo de software moderno.

Crear una API con Fastify y MongoDB

Vamos a crear una API REST que nos permita gestionar un catálogo de productos. Vamos a instalar las librerías necesarias y a generar unos puntos de acceso para operaciones básicas.

Vamos al lío. Antes de empezar, es necesario que tengas Node instalado. También vamos a necesitar instalar lo siguiente:

  • Framework Fastify
  • Mongoose, librería de Mongodb
  • Nodemon, para facilitar el desarrollo rápido de la API

Es importante que tengas nociones, al menos básicas, sobre las API REST, ya que no nos detendremos en los detalles de la implementación.

Comenzaremos configurando nuestro proyecto. Crea un directorio y desde dentro ejecuta npm init para configurar un proyecto Node.js:

mkdir api-productos
cd api-productos
npm init

Luego, instala Fastify, Mongoose y nodemon:

npm install fastify mongoose nodemon

Configuración de Fastify

Crea un archivo app.js para configurar Fastify y definir las rutas de la API:

// app.js
const fastify = require("fastify")({ logger: true })
const mongoose = require("mongoose")

mongoose.connect("mongodb://localhost/catalogo_productos", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})

fastify.get("/", async (request, reply) => {
  return { message: "¡Bienvenido a la API de Catálogo de Productos!" }
})

// Aquí definiremos las rutas

const start = async () => {
  try {
    await fastify.listen(3000)
    fastify.log.info(`Servidor en ejecución en http://localhost:3000`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

start()

Creación del modelo de Producto

Crea un modelo de Mongoose para representar los productos en MongoDB. Agrega un archivo models/product.js:

// models/product.js
const mongoose = require("mongoose")

const productSchema = new mongoose.Schema({
  name: String,
  description: String,
  price: Number,
})

module.exports = mongoose.model("Product", productSchema)

En el archivo app.js, deberás importar este esquema de la base de datos:

// app.js
const Product = require("./models/product")

Definición de rutas

Listar productos:

// app.js
fastify.get("/products", async (request, reply) => {
  const products = await Product.find()
  return products
})

Crear producto:

// app.js
fastify.post("/products", async (request, reply) => {
  const newProduct = new Product(request.body)
  await newProduct.save()
  return newProduct
})

Ver detalles de un producto:

// app.js
fastify.get("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const product = await Product.findById(productId)
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return product
})

Editar un producto:

// app.js
fastify.put("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const updatedProduct = request.body
  const product = await Product.findByIdAndUpdate(productId, updatedProduct, {
    new: true,
  })
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return product
})

Eliminar un producto:

// app.js
fastify.delete("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const product = await Product.findByIdAndRemove(productId)
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return { message: "Producto eliminado con éxito" }
})

El resultado final sería este:

// app.js
const fastify = require("fastify")({ logger: true })
const mongoose = require("mongoose")

mongoose.connect("mongodb://localhost/catalogo_productos", {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})

const Product = require("./models/product")

fastify.get("/", async (request, reply) => {
  return { message: "¡Bienvenido a la API de Catálogo de Productos!" }
})

// listar todos
fastify.get("/products", async (request, reply) => {
  const products = await Product.find()
  return products
})

// crear
fastify.post("/products", async (request, reply) => {
  const newProduct = new Product(request.body)
  await newProduct.save()
  return newProduct
})

// ver detalles
fastify.get("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const product = await Product.findById(productId)
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return product
})

// editar
fastify.put("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const updatedProduct = request.body
  const product = await Product.findByIdAndUpdate(productId, updatedProduct, {
    new: true,
  })
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return product
})

// eliminar
fastify.delete("/products/:id", async (request, reply) => {
  const productId = request.params.id
  const product = await Product.findByIdAndRemove(productId)
  if (!product) {
    reply.code(404)
    return { message: "Producto no encontrado" }
  }
  return { message: "Producto eliminado con éxito" }
})

const start = async () => {
  try {
    await fastify.listen(3000)
    fastify.log.info(`Servidor en ejecución en http://localhost:3000`)
  } catch (err) {
    fastify.log.error(err)
    process.exit(1)
  }
}

start()

Con esto hecho, ya puedes ejecutar el servidor con nodemon:

npx nodemon app.js

Con esto ya tienes los rudimentos básicos de tu API.

Soy consciente de que hay mil detalles a tener en cuenta para mejorar esta lógica, como las rutas usadas o algunas comprobaciones de errores extra, pero no es el propósito de este post.

Solo quiero plasmar mi fascinación por la simpleza y rapidez con la que podemos generar un poquito de código que sirva de base para casi cualquier proyecto.

Si quieres puedes ver un ejemplo usando Python y AWS en este otro post.

Conclusiones

En este artículo, a medida que hemos explorado la creación de una API de Catálogo de Productos con Fastify y MongoDB, hemos recordado a figuras como Grace Hopper, quienes forjaron el camino hacia la programación accesible y eficiente que disfrutamos hoy en día.

Su historia nos recuerda que, aunque el mundo de la tecnología continúa evolucionando, la pasión y la determinación de los programadores pueden dejar una huella perdurable en la historia de la informática.