Inicio > Cursos > Node.js y Express > API REST Completa
Node.js y ExpressBases de Datos y APIsLección 13 de 20

API REST Completa

Una API REST bien diseñada tiene endpoints predecibles, manejo de errores consistente, paginación, búsqueda y ordenamiento. La respuesta siempre tiene la misma estructura: { data, meta, error }. Esto facilita el consumo desde cualquier cliente.

const express = require('express');
const { PrismaClient } = require('@prisma/client');
const db = new PrismaClient();
const router = express.Router();

// GET /tareas?page=1&limit=20&q=node&orderBy=creadoEn&order=desc
router.get('/', async (req, res, next) => {
  try {
    const page  = Math.max(1, parseInt(req.query.page) || 1);
    const limit = Math.min(100, parseInt(req.query.limit) || 20);
    const skip  = (page - 1) * limit;
    const q     = req.query.q || '';
    const orderBy = req.query.orderBy || 'creadoEn';
    const order   = req.query.order === 'asc' ? 'asc' : 'desc';

    const where = q
      ? { titulo: { contains: q, mode: 'insensitive' } }
      : {};

    // Ejecutar query y count en paralelo
    const [tareas, total] = await Promise.all([
      db.tarea.findMany({
        where,
        orderBy: { [orderBy]: order },
        skip,
        take: limit,
        include: { usuario: { select: { id: true, nombre: true } } },
      }),
      db.tarea.count({ where }),
    ]);

    res.json({
      data: tareas,
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
        hasNextPage: page < Math.ceil(total / limit),
        hasPrevPage: page > 1,
      },
    });
  } catch (err) {
    next(err);
  }
});

// Respuesta de error consistente
const errorHandler = (err, req, res, next) => {
  const status = err.status || err.statusCode || 500;
  const message = status < 500 ? err.message : 'Error interno del servidor';

  res.status(status).json({
    error: {
      message,
      status,
      // solo en desarrollo:
      ...(process.env.NODE_ENV === 'development' && { stack: err.stack })
    }
  });
};

module.exports = { router, errorHandler };
ConsejoEjecuta el count y el findMany en paralelo con Promise.all(). Si los ejecutas en serie, el endpoint tarda el doble. Con paralelo, la paginación añade prácticamente cero tiempo extra.
← Mongoose y MongoDBWebSockets con Socket.io →

Practica esta lección

Resuelve los ejercicios del curso de Node.js y Express en la app, gratis y con corrección automática.

Empezar a practicar