Inicio > Cursos > Node.js y Express > Proyecto: API Tareas con Auth
Node.js y ExpressTesting y ProducciónLección 20 de 20

Proyecto: API Tareas con Auth

En este proyecto final construirás una API REST completa de gestión de tareas. Tendrá registro e inicio de sesión con JWT, contraseñas hasheadas con bcrypt, validación de datos con Zod, base de datos PostgreSQL con Prisma, y tests automatizados con Supertest y Jest.

Esta API es exactamente el tipo de backend que se construye en proyectos reales. Al terminarla entenderás el flujo completo de una petición HTTP: desde que llega al servidor, pasa por middlewares de autenticación y validación, ejecuta lógica de negocio, consulta la base de datos, y devuelve una respuesta JSON estructurada.

// src/index.js — Entry point
const app = require('./app');
const config = require('./config/env');
const { PrismaClient } = require('@prisma/client');

const db = new PrismaClient();

async function main() {
  // Verificar conexión a BD antes de arrancar
  await db.$connect();
  console.log('✅ PostgreSQL conectado');

  app.listen(config.port, () => {
    console.log(`🚀 API corriendo en http://localhost:${config.port}`);
  });
}

main().catch((err) => {
  console.error('❌ Error al iniciar:', err);
  process.exit(1);
});

// -------------------------------------------------

// src/app.js
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const authRouter = require('./routes/auth.routes');
const tareasRouter = require('./routes/tareas.routes');
const { errorHandler } = require('./middlewares/error.middleware');

const app = express();

app.use(helmet());
app.use(cors({ origin: process.env.CORS_ORIGIN }));
app.use(express.json({ limit: '10kb' }));

app.get('/health', (req, res) => res.json({ status: 'ok' }));
app.use('/api/v1/auth', authRouter);
app.use('/api/v1/tareas', tareasRouter);
app.use(errorHandler);

module.exports = app;

// -------------------------------------------------

// src/routes/tareas.routes.js
const { Router } = require('express');
const tareasController = require('../controllers/tareas.controller');
const { authMiddleware } = require('../middlewares/auth.middleware');
const { validar } = require('../middlewares/validar.middleware');
const { crearTareaSchema, actualizarTareaSchema } = require('../schemas/tarea.schema');

const router = Router();

// Todas las rutas de tareas requieren autenticación
router.use(authMiddleware);

router.get('/', tareasController.listar);
router.post('/', validar(crearTareaSchema), tareasController.crear);
router.get('/:id', tareasController.obtener);
router.patch('/:id', validar(actualizarTareaSchema), tareasController.actualizar);
router.delete('/:id', tareasController.eliminar);

module.exports = router;

// -------------------------------------------------

// src/services/tareas.service.js
const db = require('../db'); // singleton PrismaClient

const listar = async ({ usuarioId, page, limit, q }) => {
  const skip = (page - 1) * limit;
  const where = {
    usuarioId,
    ...(q && { titulo: { contains: q, mode: 'insensitive' } })
  };

  const [tareas, total] = await Promise.all([
    db.tarea.findMany({ where, skip, take: limit, orderBy: { creadoEn: 'desc' } }),
    db.tarea.count({ where }),
  ]);

  return { data: tareas, meta: { total, page, limit, totalPages: Math.ceil(total / limit) } };
};

const crear = async (datos) => db.tarea.create({ data: datos });

const obtenerPorId = async (id, usuarioId) =>
  db.tarea.findFirst({ where: { id, usuarioId } });

const actualizar = async (id, usuarioId, datos) =>
  db.tarea.updateMany({ where: { id, usuarioId }, data: datos });

const eliminar = async (id, usuarioId) =>
  db.tarea.deleteMany({ where: { id, usuarioId } });

module.exports = { listar, crear, obtenerPorId, actualizar, eliminar };
ConsejoEl patrón deleteMany/updateMany con { id, usuarioId } en el where es una técnica de seguridad: garantiza que un usuario solo puede modificar SUS propias tareas, sin necesidad de un check separado.
← Deploy con PM2 y Nginx

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