Guía de Migración: v3.x a v4.x
Esta guía te ayuda a migrar de YasuiJS 3.x (basado en Express) a YasuiJS 4.x (Web Standards con SRVX).
Resumen de Cambios
YasuiJS 4.x representa un cambio arquitectónico importante:
- Eliminada la dependencia de Express - Ahora usa Web Standards
- createServer() - Usa srvx para Node.js, Deno y Bun
- createApp() - Devuelve un manejador fetch estándar para cualquier plataforma Web Standards
- Listo para Edge - Despliega en Cloudflare Workers, Vercel Edge, Netlify Edge, Deno Deploy (vía createApp)
- Compatible con Serverless - Funciona con AWS Lambda, Vercel Functions, Netlify Functions (vía createApp)
- Cambios incompatibles - Los middlewares de Express ya no son compatibles
- Nuevas características - Soporte TLS/HTTPS, HTTP/2 en Node.js
Cambios Incompatibles
1. Los Middlewares de Express No Son Compatibles
Antes (v3.x):
import cors from 'cors';
import helmet from 'helmet';
yasui.createServer({
middlewares: [cors(), helmet()]
});Después (v4.x): Los middlewares de Express no son compatibles. Debes:
- Encontrar alternativas compatibles con Web Standards
- Escribir middlewares nativos de YasuiJS
@Middleware()
export class CorsMiddleware implements IMiddleware {
async use(@Req() req: Request, @Next() next: NextFunction) {
const response = await next();
const headers = new Headers(response.headers);
headers.set('Access-Control-Allow-Origin', '*');
headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH');
headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
});
}
}
yasui.createServer({
middlewares: [CorsMiddleware]
});2. El Objeto Response Ya No Es Compatible
@Res() está eliminado - ya no es compatible.
Antes (v3.x):
@Middleware()
export class AuthMiddleware {
use(@Req() req: Request, @Res() res: Response) {
if (!req.headers.authorization) {
// Usar @Res() era posible pero no recomendado
res.status(401).json({ error: 'Unauthorized' });
return;
}
}
}Después (v4.x):
@Middleware()
export class AuthMiddleware {
use(@Req() req: Request) {
if (!req.headers.get('authorization')) {
// Lanza errores o devuelve objetos Response
throw new HttpError(401, 'Unauthorized');
}
// Continuará al siguiente middleware o controlador si no devuelves nada/void
}
}3. Cambios en el Objeto Request
@Req() proporciona un objeto Request estándar web, en lugar de Express; solo algunas propiedades siguen siendo compatibles.
Propiedades compatibles con Express (aún disponibles):
req.path- Pathname sin query stringreq.hostname- Host sin puertoreq.protocol- "http" o "https"req.ip- Dirección IP del clientereq.query- Objeto query parseadoreq.cookies- Objeto cookies parseadoreq.body- Cuerpo de la petición parseadoreq.headers- Devuelve objeto plano para acceso a propiedades
Después (v4.x):
@Get('/users')
getUsers(@Req() req: Request) {
// Headers vía .get() en el objeto Headers nativo
const auth = req.headers.get('authorization');
// Las propiedades compatibles con Express aún funcionan
const auth = req.headers.authorization;
const page = req.query.page;
const path = req.path;
}4. Cambios en el Manejo de Respuestas Personalizadas
Antes (v3.x):
@Get('/custom')
customResponse(@Res() res: Response) {
res.status(418).json({ message: "I'm a teapot" });
}Después (v4.x):
@Get('/custom')
customResponse() {
// Opción 1: Devolver Response de Web Standards
return new Response(JSON.stringify({ message: "I'm a teapot" }), {
status: 418,
headers: { 'Content-Type': 'application/json' }
});
}5. Tipo de Retorno de createApp()
Antes (v3.x):
import express from 'express';
const app = yasui.createApp({ controllers: [UserController] });
// app es una Aplicación Express
app.use(express.json());
app.listen(3000);Después (v4.x):
import { serve } from 'srvx';
const app = yasui.createApp({ controllers: [UserController] });
// app es FetchHandler { fetch: Function }
serve({
fetch: app.fetch,
port: 3000
});6. Cambios en la Configuración
Antes (v3.x):
yasui.createServer({
controllers: [UserController],
middlewares: [cors(), helmet()],
protocol: 'http',
port: 3000
});Después (v4.x):
yasui.createServer({
controllers: [UserController],
middlewares: [CorsMiddleware], // Solo middlewares de YasuiJS
port: 3000,
tls: { // Nuevo: soporte TLS/HTTPS
cert: './cert.pem',
key: './key.pem'
},
runtimeOptions: { // Nuevo: opciones específicas del runtime
node: {
http2: true
}
}
});Nuevas opciones:
tls- Configuración TLS/HTTPShostname- Hostname del servidorruntimeOptions- Configuración específica del runtime
Obsoleto:
protocol- Auto-determinado por la configuracióntls
Pasos de Migración
Paso 1: Actualizar Dependencias
npm install yasui@latest
# o
pnpm update yasuiCambios en Swagger UI:
YasuiJS v4 sirve los assets de Swagger UI desde CDN por defecto - no se necesitan paquetes adicionales.
Si estabas usando swagger-ui-express en v3:
npm uninstall swagger-ui-express
# o
pnpm remove swagger-ui-expressNo se necesitan cambios de código - Swagger UI funciona inmediatamente sin configuración. El enfoque CDN también permite que Swagger UI funcione en todos los runtimes, incluyendo entornos edge.
Paso 2: Eliminar Middlewares de Express
Identifica todos los middlewares de Express en tu código:
// ELIMINAR estos
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
yasui.createServer({
middlewares: [cors(), helmet(), morgan('dev')] // ❌ Ya no funciona
});Paso 3: Reemplazar con Middlewares Nativos
Escribe middlewares de YasuiJS para cada característica:
// Crear middleware CORS nativo
@Middleware()
export class CorsMiddleware implements IMiddleware {
async use(@Req() req: Request, @Next() next: NextFunction) {
const response = await next();
const headers = new Headers(response.headers);
headers.set('Access-Control-Allow-Origin', '*');
return new Response(response.body, {
status: response.status,
headers,
});
}
}
// Crear middleware de logging nativo
@Middleware()
export class LoggingMiddleware implements IMiddleware {
async use(@Req() req: Request, @Logger() logger: LoggerService, @Next() next: NextFunction) {
logger.log(`${req.method} ${req.path}`);
return await next();
}
}
yasui.createServer({
middlewares: [CorsMiddleware, LoggingMiddleware] // ✅ Funciona
});Paso 4: Actualizar Firmas de Middlewares
Elimina el uso de @Res() de todos los middlewares: lanza new HttpError para estado de error, o devuelve valor.
Recuerda: Los middlewares funcionan como métodos de controlador. No necesitas llamar next() a menos que quieras modificar la respuesta.
Paso 6: Actualizar Manejo Manual de Respuestas
Reemplaza los métodos de respuesta de Express con Web Standards:
Antes:
@Get('/file')
downloadFile(@Res() res: Response) {
res.sendFile('/path/to/file.pdf');
}
@Get('/redirect')
redirect(@Res() res: Response) {
res.redirect('/new-location');
}Después:
@Get('/file')
async downloadFile() {
const file = await Deno.readFile('/path/to/file.pdf'); // o fs.readFile
return new Response(file, {
headers: {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="file.pdf"'
}
});
}
@Get('/redirect')
redirect() {
return new Response(null, {
status: 302,
headers: { 'Location': '/new-location' }
});
}Paso 7: Actualizar Uso de createApp()
Si estabas usando createApp() para configuración personalizada del servidor:
Antes:
const app = yasui.createApp({ controllers: [UserController] });
app.use(express.static('public'));
app.listen(3000);Después:
import { serve } from 'srvx';
const app = yasui.createApp({ controllers: [UserController] });
serve({
fetch: app.fetch,
port: 3000,
static: { // servir archivos estáticos con srvx
'/': './public'
}
});Paso 8: Probar Tu Aplicación
- Inicia tu servidor
- Prueba todos los endpoints
- Verifica el comportamiento de los middlewares
- Comprueba el manejo de errores
- Prueba con diferentes runtimes (Node.js, Deno, Bun)
Nuevas Características en v4.x
Soporte TLS/HTTPS
yasui.createServer({
controllers: [UserController],
port: 443,
tls: {
cert: './certs/cert.pem',
key: './certs/key.pem',
passphrase: 'opcional'
}
});Soporte HTTP/2 (Node.js)
yasui.createServer({
controllers: [UserController],
tls: {
cert: './cert.pem',
key: './key.pem'
},
runtimeOptions: {
node: {
http2: true // Habilitado por defecto con TLS
}
}
});Multi-Runtime y Despliegue Edge
El mismo código funciona en diferentes runtimes y plataformas:
// Runtimes tradicionales
// Funciona en Node.js, Deno y Bun
yasui.createServer({
controllers: [UserController],
port: 3000
});
// Runtimes Edge - usa createApp()
const app = yasui.createApp({
controllers: [UserController]
});
// Cloudflare Workers
export default {
fetch: app.fetch
};
// Vercel Edge Functions
export const GET = app.fetch;
export const POST = app.fetch;
// Deno Deploy
Deno.serve(app.fetch);
// Netlify Edge Functions
export default app.fetch;Despliega en Cualquier Lugar
Dado que YasuiJS devuelve un manejador fetch estándar, puedes desplegar en:
- Servidores tradicionales: Node.js, Deno, Bun
- Runtimes Edge: Cloudflare Workers, Vercel Edge, Netlify Edge, Deno Deploy
- Serverless: AWS Lambda (con adaptadores), Vercel Functions, Netlify Functions
- Cualquier plataforma que soporte manejadores fetch de Web Standards
Obtener Ayuda
Si encuentras problemas durante la migración:
- Consulta la documentación
- Revisa los ejemplos
- Abre un issue en GitHub