Saltearse al contenido

Adaptador Express

El adaptador Express de Veloce-TS te permite montar una aplicación Veloce-TS dentro de una app Express.js existente — o usar Express como capa de transporte HTTP. Es útil cuando migras de Express a Veloce-TS de forma incremental, o cuando necesitas middleware exclusivo de Express (Passport.js, multer, sesiones, etc.).

:::note Reescritura en v0.4.0 El adaptador Express fue completamente reescrito en v0.4.0 para compatibilidad total con ESM, manejo correcto del body y delegación apropiada de errores. Si usabas una versión anterior, revisa las notas de migración. :::


Express es una peer dependency — instálala junto a Veloce-TS:

Ventana de terminal
# Usando Bun
bun add veloce-ts express
bun add -d @types/express
# Usando npm
npm install veloce-ts express
npm install --save-dev @types/express

import express from 'express';
import { VeloceTS, Controller, Get, Post, Body } from 'veloce-ts';
import { ExpressAdapter } from 'veloce-ts/adapters/express';
import { z } from 'zod';
// 1. Define tu app Veloce-TS normalmente
const UsuarioSchema = z.object({
nombre: z.string().min(2),
email: z.string().email(),
});
@Controller('/usuarios')
class UsuarioController {
@Get('/')
async listar() {
return [{ id: 1, nombre: 'Juan' }];
}
@Post('/')
async crear(@Body(UsuarioSchema) usuario: z.infer<typeof UsuarioSchema>) {
return { id: 2, ...usuario };
}
}
const veloce = new VeloceTS({ title: 'Mi API', docs: true });
veloce.include(UsuarioController);
await veloce.compile();
// 2. Crea una app Express y monta Veloce-TS
const app = express();
app.use(express.json());
// Monta el adaptador — maneja todas las peticiones bajo /api
const adapter = new ExpressAdapter(veloce);
app.use('/api', adapter.getRouter());
// Puedes tener rutas Express normales junto a las de Veloce-TS
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
app.listen(3000, () => {
console.log('Servidor en http://localhost:3000');
console.log('Rutas Veloce-TS en http://localhost:3000/api');
console.log('Swagger UI en http://localhost:3000/api/docs');
});

El adaptador v0.4.0 acepta una app Express pre-creada como segundo argumento. Esto permite agregar middleware (auth, rate limiting, multipart, etc.) que se ejecuta antes de que las peticiones lleguen a Veloce-TS:

import express from 'express';
import passport from 'passport';
import multer from 'multer';
import { ExpressAdapter } from 'veloce-ts/adapters/express';
const expressApp = express();
// Agrega el middleware Express que necesites
expressApp.use(express.json());
expressApp.use(express.urlencoded({ extended: true }));
expressApp.use(passport.initialize());
const upload = multer({ dest: 'uploads/' });
// Crea el adaptador pasando la app Express pre-configurada
const adapter = new ExpressAdapter(veloce, expressApp);
expressApp.use('/api', adapter.getRouter());
expressApp.listen(3000);

Monta Veloce-TS en cualquier sub-ruta de tu app Express:

const mainApp = express();
mainApp.use(express.json());
// API v1 con Veloce-TS
const v1Adapter = new ExpressAdapter(veloceV1App);
mainApp.use('/api/v1', v1Adapter.getRouter());
// API v2 con otra app Veloce-TS
const v2Adapter = new ExpressAdapter(veloceV2App);
mainApp.use('/api/v2', v2Adapter.getRouter());
// Rutas legadas en Express
mainApp.use('/legacy', legacyRouter);
mainApp.listen(3000);

El adaptador v0.4.0 delega correctamente los errores inesperados al pipeline de errores de Express via next(err):

import express, { Request, Response, NextFunction } from 'express';
import { ExpressAdapter } from 'veloce-ts/adapters/express';
const app = express();
app.use(express.json());
const adapter = new ExpressAdapter(veloce);
app.use('/api', adapter.getRouter());
// Este handler de errores se llama para errores no manejados
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error('Error no manejado:', err);
res.status(500).json({
error: 'Error interno del servidor',
message: process.env.NODE_ENV === 'development' ? err.message : undefined,
});
});
app.listen(3000);

El adaptador v0.4.0 maneja correctamente tanto bodies raw (Buffer) como pre-parseados:

  • JSON/urlencoded: Si el middleware Express ya parseó el body, el adaptador usa el valor parseado
  • Buffer raw: Si el body es raw (p.ej. webhooks, subida de archivos), se pasa correctamente
  • Header transfer-encoding: El adaptador omite este header al reenviar respuestas (era fuente de bugs en versiones anteriores)

// Antes (v0.3.x)
import { ExpressAdapter } from 'veloce-ts';
// Ahora (v0.4.0)
import { ExpressAdapter } from 'veloce-ts/adapters/express';

El adaptador ya no necesita workarounds como declare const require: any. Usa Function('return require')() internamente para cargar Express de forma lazy, lo que funciona perfectamente en proyectos ESM.


EscenarioRecomendación
Proyecto nuevoUsar Veloce-TS standalone (adaptador Hono) para mejor rendimiento
Migrar una app Express a Veloce-TSUsar el adaptador para migrar ruta por ruta
Necesitas Passport.js, multer u otro middleware solo de ExpressUsar el adaptador
Plataforma que solo soporta ExpressUsar el adaptador
Necesitas máximo rendimientoUsar Veloce-TS standalone