Construyendo una API con Express + Bun + TypeScript + express-validator
¿Estás buscando una forma ultrarrápida y moderna de construir APIs con Express? En este post vamos a crear una base sólida de backend utilizando:
- 🐰 Bun: un runtime de JavaScript y TypeScript extremadamente rápido.
- ⚙️ Express: el framework web clásico de Node, ahora corriendo sobre Bun.
- 🧠 TypeScript: para desarrollo tipado y seguro.
- ✅ express-validator: para validar entradas de forma sencilla y declarativa.
Vamos a crear una pequeña API REST con validación, escrita en TypeScript y ejecutada con Bun.
🚀 ¿Por qué usar Bun?
Bun es un runtime moderno (como Node.js o Deno), pero enfocado en el rendimiento:
- 🔥 Compila TypeScript y transpila ES6+ sin configuración.
- ⚡ ¡Hasta 20 veces más rápido en benchmarks que Node en ciertas tareas!
- 🧩 Incluye gestor de paquetes (
bun install
) y bundler.
📦 Requisitos
curl -fsSL https://bun.sh/install | bash
Asegúrate de reiniciar la terminal tras instalarlo, o añade Bun al PATH manualmente.
🛠️ Inicializando el proyecto
bun init express-api
cd express-api
Selecciona la plantilla typescript
, o edítalo después.
Instalar dependencias
bun add express express-validator
bun add -d @types/express @types/express-validator
📁 Estructura del proyecto
express-api/
├── src/
│ ├── index.ts
│ ├── routes/
│ │ └── users.ts
│ └── validators/
│ └── userValidator.ts
├── tsconfig.json
├── bunfig.toml
└── package.json (opcional)
⚙️ Configuración de TypeScript (tsconfig.json
)
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
📄 src/index.ts
import express from 'express';
import { json } from 'body-parser';
import userRoutes from './routes/users';
const app = express();
const PORT = process.env.PORT || 3000;
app.use(json());
app.use('/api/users', userRoutes);
app.listen(PORT, () => {
console.log(`🚀 Servidor escuchando en http://localhost:${PORT}`);
});
📄 src/routes/users.ts
import { Router } from 'express';
import { body, validationResult } from 'express-validator';
import { createUserValidator } from '../validators/userValidator';
const router = Router();
router.post(
'/',
createUserValidator,
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { name, email } = req.body;
return res.status(201).json({
message: 'Usuario creado correctamente',
user: { name, email }
});
}
);
export default router;
📄 src/validators/userValidator.ts
import { body } from 'express-validator';
export const createUserValidator = [
body('name')
.notEmpty().withMessage('El nombre es obligatorio')
.isLength({ min: 2 }).withMessage('El nombre debe tener al menos 2 caracteres'),
body('email')
.isEmail().withMessage('Debe ser un email válido'),
];
🚀 Ejecutar el servidor
Bun detecta automáticamente TypeScript. Ejecuta:
bun src/index.ts
Verás en consola:
🚀 Servidor escuchando en http://localhost:3000
📬 Probar la API
POST /api/users
✅ Cuerpo válido:
{
"name": "Ada Lovelace",
"email": "[email protected]"
}
Respuesta:
{
"message": "Usuario creado correctamente",
"user": {
"name": "Ada Lovelace",
"email": "[email protected]"
}
}
❌ Cuerpo inválido:
{
"name": "",
"email": "noesunemail"
}
Respuesta:
{
"errors": [
{
"msg": "El nombre es obligatorio",
"param": "name",
"location": "body"
},
{
"msg": "Debe ser un email válido",
"param": "email",
"location": "body"
}
]
}
💡 Ventajas de esta stack
- ⚡ Velocidad: Bun compila y ejecuta TypeScript directamente.
- ✅ Validación robusta: express-validator permite definir reglas claras y centralizadas.
- 🧼 Código limpio: separando rutas, validaciones y lógica.
- 🚀 Listo para producción: puedes extender con bases de datos, auth, middlewares, etc.
🧠 Conclusión
Usar Express con Bun y TypeScript es una excelente forma de construir APIs rápidas, escalables y modernas. Puedes mantener la simplicidad de Express mientras te beneficias de la velocidad de Bun y la seguridad de TypeScript.
¿Te gustaría que hagamos una versión con base de datos (SQLite o PostgreSQL), autenticación o Docker? ¡Déjame un comentario y lo armamos juntos!