expressed-example-app 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +136 -0
- package/app.js +144 -92
- package/changelog-core-enrutador.md +177 -0
- package/controllers/mainController.js +96 -0
- package/controllers/productController.js +50 -0
- package/controllers/userController.js +48 -0
- package/documentacion-bug-enrutamiento.md +114 -0
- package/hooks-config.js +42 -0
- package/hooks-personalizados.js +54 -0
- package/package.json +29 -43
- package/queue-system.js +128 -0
- package/routes/main-routes.json +37 -0
- package/routes/queue-routes.json +44 -0
- package/test-hooks.js +31 -0
- package/test-routes.json +9 -0
- package/config/routes.json +0 -70
- package/controllers/EndpointController.js +0 -43
- package/controllers/HomeController.js +0 -19
- package/controllers/ProductController.js +0 -47
- package/controllers/QueueController.js +0 -26
- package/controllers/UserController.js +0 -73
- package/hooks/AppHooks.js +0 -60
- package/middleware/bodyCapture.js +0 -20
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Express-Router-BDS Example Application
|
|
2
|
+
|
|
3
|
+
This is a sample Express.js application demonstrating the usage of the `express-router-bds` routing system with custom hooks, advanced features, and integrated queue system.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This example application showcases:
|
|
8
|
+
|
|
9
|
+
- High-performance routing with `express-router-bds`
|
|
10
|
+
- JSON-based route configuration
|
|
11
|
+
- Custom hook system implementation
|
|
12
|
+
- Parameterized route handling
|
|
13
|
+
- Directory-based route loading
|
|
14
|
+
- Integrated queue system with `express-queued`
|
|
15
|
+
- Declarative route definitions in separate JSON files
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Modular Route Configuration**: Routes defined in JSON files for easy maintenance
|
|
20
|
+
- **Custom Hooks**: Comprehensive hook system with `pre_route_load`, `post_route_load`, `before_route_handler`, `after_route_handler`, `route_handler_error`, and more
|
|
21
|
+
- **Parameterized Routes**: Support for dynamic routes like `/users/:id` and `/products/:category/:id`
|
|
22
|
+
- **Integrated Queue System**: Background task processing with `express-queued`
|
|
23
|
+
- **Declarative Routes**: Separate route files for different functionalities
|
|
24
|
+
- **Extensible Architecture**: Easy to extend with custom middleware and hooks
|
|
25
|
+
|
|
26
|
+
## Project Structure
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
express-app/
|
|
30
|
+
├── app.js # Main application entry point
|
|
31
|
+
├── queue-system.js # Queue system integration
|
|
32
|
+
├── hooks-config.js # Base hook configurations
|
|
33
|
+
├── hooks-personalizados.js # Custom hook implementations
|
|
34
|
+
├── controllers/
|
|
35
|
+
│ ├── mainController.js # Home, init and queue route handlers
|
|
36
|
+
│ ├── productController.js # Product route handlers
|
|
37
|
+
│ └── userController.js # User route handlers
|
|
38
|
+
├── routes/
|
|
39
|
+
│ ├── main-routes.json # Main route definitions in JSON format
|
|
40
|
+
│ └── queue-routes.json # Queue-related route definitions
|
|
41
|
+
└── node_modules/
|
|
42
|
+
├── express-router-bds/ # Custom routing system
|
|
43
|
+
└── express-queued/ # Queue system
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Available Endpoints
|
|
47
|
+
|
|
48
|
+
### Main Endpoints
|
|
49
|
+
- `GET /` - Home page with welcome message
|
|
50
|
+
- `GET /init` - Initialization endpoint
|
|
51
|
+
- `GET /users/:id` - Get user by ID
|
|
52
|
+
- `GET /products/:category/:id` - Get product by category and ID
|
|
53
|
+
- `GET /test-hook` - Test endpoint for hook demonstration
|
|
54
|
+
|
|
55
|
+
### Queue System Endpoints
|
|
56
|
+
- `GET /queue-status` - Get the status of the queue system
|
|
57
|
+
- `GET /start-queues` - Start the queue system
|
|
58
|
+
- `GET /stop-queues` - Stop the queue system
|
|
59
|
+
- `POST /process-user` - Add a user processing task to the queue
|
|
60
|
+
- `POST /process-product` - Add a product processing task to the queue
|
|
61
|
+
- `POST /send-email` - Add an email sending task to the queue
|
|
62
|
+
|
|
63
|
+
## Queue System
|
|
64
|
+
|
|
65
|
+
The application integrates `express-queued` for background task processing:
|
|
66
|
+
|
|
67
|
+
- **Multiple Queues**: Dedicated queues for different types of tasks
|
|
68
|
+
- **Configurable Concurrency**: Control how many tasks execute simultaneously per queue
|
|
69
|
+
- **Retry System**: Automatic failure handling with configurable retries
|
|
70
|
+
- **Priority Management**: Assign priorities to tasks
|
|
71
|
+
- **Hooks Integration**: Customize processing with hooks
|
|
72
|
+
|
|
73
|
+
### Queue Types
|
|
74
|
+
- `procesamiento-general` - General processing tasks
|
|
75
|
+
- `envio-correos` - Email sending tasks
|
|
76
|
+
- `procesamiento-usuarios` - User processing tasks
|
|
77
|
+
- `procesamiento-productos` - Product processing tasks
|
|
78
|
+
|
|
79
|
+
## Hook System
|
|
80
|
+
|
|
81
|
+
The application demonstrates several types of hooks:
|
|
82
|
+
|
|
83
|
+
- `pre_route_load` - Executes before loading routes from a file
|
|
84
|
+
- `post_route_load` - Executes after loading routes from a file
|
|
85
|
+
- `before_route_processing` - Executes before processing any route
|
|
86
|
+
- `route_matched` - Executes when a matching route is found
|
|
87
|
+
- `before_route_handler` - Executes before executing a route handler
|
|
88
|
+
- `after_route_handler` - Executes after executing a route handler
|
|
89
|
+
- `route_handler_error` - Executes when a route handler error occurs
|
|
90
|
+
|
|
91
|
+
## Installation
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npm install
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Usage
|
|
98
|
+
|
|
99
|
+
Start the server:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm start
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The application will be available at `http://localhost:3000`
|
|
106
|
+
|
|
107
|
+
## Testing
|
|
108
|
+
|
|
109
|
+
Test the main endpoints:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
curl http://localhost:3000
|
|
113
|
+
curl http://localhost:3000/users/123
|
|
114
|
+
curl http://localhost:3000/products/electronics/456
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Test the queue system:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Check queue status
|
|
121
|
+
curl http://localhost:3000/queue-status
|
|
122
|
+
|
|
123
|
+
# Add a user processing task
|
|
124
|
+
curl -X POST http://localhost:3000/process-user \
|
|
125
|
+
-H "Content-Type: application/json" \
|
|
126
|
+
-d '{"userId": "123", "name": "John Doe", "email": "john@example.com"}'
|
|
127
|
+
|
|
128
|
+
# Add an email sending task
|
|
129
|
+
curl -X POST http://localhost:3000/send-email \
|
|
130
|
+
-H "Content-Type: application/json" \
|
|
131
|
+
-d '{"to": "test@example.com", "subject": "Test", "content": "Test content"}'
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
This project is part of the `express-router-bds` ecosystem and follows the same licensing terms.
|
package/app.js
CHANGED
|
@@ -1,115 +1,167 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Aplicación principal
|
|
3
|
-
* Integración de @hooked, @router y @queued con una arquitectura limpia
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
const express = require('express');
|
|
7
|
-
const fs = require('fs');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const ExpressHooked = require('express-hooked');
|
|
10
2
|
const ExpressRouterIntegration = require('express-router-bds');
|
|
11
|
-
const
|
|
12
|
-
const AppHooks = require('./hooks
|
|
13
|
-
const
|
|
3
|
+
const RouteDirectoryLoader = require('express-router-bds/RouteDirectoryLoader');
|
|
4
|
+
const AppHooks = require('./hooks-config');
|
|
5
|
+
const HooksPersonalizados = require('./hooks-personalizados');
|
|
6
|
+
const QueueSystem = require('./queue-system');
|
|
14
7
|
|
|
15
|
-
// Crear la aplicación Express
|
|
16
8
|
const app = express();
|
|
17
|
-
const
|
|
9
|
+
const PORT = process.env.PORT || 3000;
|
|
18
10
|
|
|
19
|
-
//
|
|
20
|
-
const
|
|
11
|
+
// Crear instancia del router
|
|
12
|
+
const routerIntegration = new ExpressRouterIntegration();
|
|
21
13
|
|
|
22
|
-
//
|
|
23
|
-
const
|
|
14
|
+
// Crear instancia del sistema de colas
|
|
15
|
+
const queueSystem = new QueueSystem();
|
|
24
16
|
|
|
25
|
-
// Inicializar
|
|
26
|
-
const
|
|
17
|
+
// Inicializar hooks y filtros
|
|
18
|
+
const appHooks = new AppHooks(app, routerIntegration.getHooks());
|
|
27
19
|
|
|
28
|
-
// Inicializar
|
|
29
|
-
const
|
|
20
|
+
// Inicializar hooks personalizados
|
|
21
|
+
const hooksPersonalizados = new HooksPersonalizados(routerIntegration);
|
|
30
22
|
|
|
31
|
-
//
|
|
32
|
-
|
|
23
|
+
// Cargar rutas desde directorio
|
|
24
|
+
const routeDirectoryLoader = new RouteDirectoryLoader();
|
|
33
25
|
|
|
34
|
-
// Middleware para
|
|
35
|
-
app.use(
|
|
26
|
+
// Middleware para parsear JSON
|
|
27
|
+
app.use(express.json());
|
|
36
28
|
|
|
37
|
-
// Middleware para
|
|
38
|
-
app.use(
|
|
29
|
+
// Middleware para inyectar el sistema de colas en las solicitudes
|
|
30
|
+
app.use(queueSystem.getInstance().queueMiddleware());
|
|
39
31
|
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Importar el controlador
|
|
51
|
-
const Controller = require(controllerPath);
|
|
52
|
-
|
|
53
|
-
// Verificar si la acción existe en el controlador
|
|
54
|
-
if (Controller[actionName]) {
|
|
55
|
-
// Registrar la ruta con el método HTTP, la ruta y el controlador
|
|
56
|
-
router.addRoute(route.method, route.path, (req, res) => {
|
|
57
|
-
// Disparar hook antes de ejecutar la acción
|
|
58
|
-
hooked.doAction('before_controller_action', req, res, route);
|
|
59
|
-
|
|
60
|
-
// Disparar hook para mostrar información detallada de la solicitud
|
|
61
|
-
// Usar el body capturado en lugar del body original que puede estar vacío
|
|
62
|
-
if (req.capturedBody) {
|
|
63
|
-
req.body = req.capturedBody;
|
|
64
|
-
}
|
|
65
|
-
hooked.doAction('request_details_log', req, res, route);
|
|
66
|
-
|
|
67
|
-
// Ejecutar la acción del controlador
|
|
68
|
-
Controller[actionName](req, res);
|
|
69
|
-
|
|
70
|
-
// Disparar hook después de ejecutar la acción
|
|
71
|
-
hooked.doAction('after_controller_action', req, res, route);
|
|
72
|
-
});
|
|
73
|
-
} else {
|
|
74
|
-
console.error(`La acción "${actionName}" no existe en el controlador "${controllerName}"`);
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
console.error(`El archivo del controlador "${controllerPath}" no existe`);
|
|
32
|
+
// Middleware para inyectar el sistema de rutas en las solicitudes
|
|
33
|
+
app.use((req, res, next) => {
|
|
34
|
+
req.routerIntegration = routerIntegration;
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
routerIntegration.addHook('route_matched', (matchedRoute, req, res) => {
|
|
39
|
+
console.log(`Ruta encontrada: ${matchedRoute.route.path}`);
|
|
40
|
+
if (matchedRoute.params && Object.keys(matchedRoute.params).length > 0) {
|
|
41
|
+
console.log(`Parámetros:`, matchedRoute.params);
|
|
78
42
|
}
|
|
79
|
-
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Cargar rutas desde el directorio
|
|
46
|
+
routeDirectoryLoader.loadRoutesFromDirectory(routerIntegration, './routes')
|
|
47
|
+
.then(routes => {
|
|
48
|
+
console.log(`${routes.length} rutas cargadas desde directorio`);
|
|
49
|
+
// Mostrar las rutas que se han cargado
|
|
50
|
+
routes.forEach(route => {
|
|
51
|
+
console.log(`Ruta cargada: ${route.method} ${route.path}`);
|
|
52
|
+
});
|
|
53
|
+
})
|
|
54
|
+
.catch(error => {
|
|
55
|
+
console.error('Error cargando rutas desde directorio:', error.message);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Cargar rutas específicas de colas
|
|
59
|
+
const RouteLoader = require('express-router-bds/RouteLoader');
|
|
60
|
+
const queueRouteLoader = new RouteLoader();
|
|
61
|
+
queueRouteLoader.loadRoutes(routerIntegration, './routes/queue-routes.json')
|
|
62
|
+
.then(queueRoutes => {
|
|
63
|
+
console.log(`${queueRoutes.length} rutas de colas cargadas`);
|
|
64
|
+
queueRoutes.forEach(route => {
|
|
65
|
+
console.log(`Ruta de cola cargada: ${route.method} ${route.path}`);
|
|
66
|
+
});
|
|
67
|
+
})
|
|
68
|
+
.catch(error => {
|
|
69
|
+
console.error('Error cargando rutas de colas:', error.message);
|
|
70
|
+
});
|
|
80
71
|
|
|
81
|
-
// Aplicar el
|
|
82
|
-
|
|
72
|
+
// Aplicar el router a la aplicación Express
|
|
73
|
+
routerIntegration.applyToApp(app);
|
|
83
74
|
|
|
84
|
-
//
|
|
85
|
-
|
|
75
|
+
// Middleware para manejar errores 404
|
|
76
|
+
app.use((req, res) => {
|
|
77
|
+
res.status(404).json({ error: 'Ruta no encontrada' });
|
|
78
|
+
});
|
|
86
79
|
|
|
87
|
-
//
|
|
88
|
-
|
|
80
|
+
// Ruta para obtener el estado del sistema de colas
|
|
81
|
+
app.get('/queue-status', (req, res) => {
|
|
82
|
+
const status = req.getQueueStatus();
|
|
83
|
+
res.json(status);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Ruta para iniciar el sistema de colas
|
|
87
|
+
app.get('/start-queues', (req, res) => {
|
|
88
|
+
queueSystem.start();
|
|
89
|
+
res.json({ message: 'Sistema de colas iniciado' });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Ruta para detener el sistema de colas
|
|
93
|
+
app.get('/stop-queues', (req, res) => {
|
|
94
|
+
queueSystem.stop();
|
|
95
|
+
res.json({ message: 'Sistema de colas detenido' });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Ruta para procesar un usuario en cola
|
|
99
|
+
app.post('/process-user', (req, res) => {
|
|
100
|
+
const { userId, name, email } = req.body;
|
|
101
|
+
|
|
102
|
+
if (!userId) {
|
|
103
|
+
return res.status(400).json({ error: 'userId es requerido' });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const taskId = queueSystem.addUserProcessingTask({ userId, name, email });
|
|
107
|
+
|
|
108
|
+
res.json({
|
|
109
|
+
message: 'Tarea de procesamiento de usuario agregada a la cola',
|
|
110
|
+
taskId
|
|
111
|
+
});
|
|
112
|
+
});
|
|
89
113
|
|
|
90
|
-
//
|
|
91
|
-
|
|
114
|
+
// Ruta para procesar un producto en cola
|
|
115
|
+
app.post('/process-product', (req, res) => {
|
|
116
|
+
const { productId, name, price } = req.body;
|
|
117
|
+
|
|
118
|
+
if (!productId) {
|
|
119
|
+
return res.status(400).json({ error: 'productId es requerido' });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const taskId = queueSystem.addProductProcessingTask({ productId, name, price });
|
|
123
|
+
|
|
124
|
+
res.json({
|
|
125
|
+
message: 'Tarea de procesamiento de producto agregada a la cola',
|
|
126
|
+
taskId
|
|
127
|
+
});
|
|
128
|
+
});
|
|
92
129
|
|
|
93
|
-
//
|
|
94
|
-
app.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
// Ruta para enviar un correo en cola
|
|
131
|
+
app.post('/send-email', (req, res) => {
|
|
132
|
+
const { to, subject, content } = req.body;
|
|
133
|
+
|
|
134
|
+
if (!to) {
|
|
135
|
+
return res.status(400).json({ error: 'to es requerido' });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const taskId = queueSystem.addEmailSendingTask({ to, subject, content });
|
|
139
|
+
|
|
140
|
+
res.json({
|
|
141
|
+
message: 'Tarea de envío de correo agregada a la cola',
|
|
142
|
+
taskId
|
|
99
143
|
});
|
|
100
144
|
});
|
|
101
145
|
|
|
102
146
|
// Iniciar el servidor
|
|
103
|
-
app.listen(
|
|
104
|
-
console.log(`Servidor corriendo en
|
|
105
|
-
console.log('
|
|
106
|
-
console.log('-
|
|
107
|
-
console.log('-
|
|
108
|
-
console.log('-
|
|
147
|
+
app.listen(PORT, () => {
|
|
148
|
+
console.log(`Servidor corriendo en el puerto ${PORT}`);
|
|
149
|
+
console.log('Endpoints disponibles:');
|
|
150
|
+
console.log('- GET /');
|
|
151
|
+
console.log('- GET /init');
|
|
152
|
+
console.log('- GET /users/:id');
|
|
153
|
+
console.log('- GET /products/:category/:id');
|
|
154
|
+
console.log('- GET /test-hook');
|
|
155
|
+
console.log('- GET /queue-status');
|
|
156
|
+
console.log('- GET /start-queues');
|
|
157
|
+
console.log('- GET /stop-queues');
|
|
158
|
+
console.log('- POST /process-user');
|
|
159
|
+
console.log('- POST /process-product');
|
|
160
|
+
console.log('- POST /send-email');
|
|
109
161
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
162
|
+
// Iniciar el sistema de colas
|
|
163
|
+
queueSystem.start();
|
|
164
|
+
console.log('Sistema de colas iniciado');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
module.exports = app;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Changelog Detallado: Modificaciones al Core de Express-Router-BDS
|
|
2
|
+
|
|
3
|
+
## Archivo: `/node_modules/express-router-bds/ExpressRouter.js`
|
|
4
|
+
|
|
5
|
+
### Cambio 1: Llamada al hook `before_route_processing`
|
|
6
|
+
- **Fecha**: 15 de febrero de 2026
|
|
7
|
+
- **Línea(s)**: 154
|
|
8
|
+
- **Antes**:
|
|
9
|
+
```javascript
|
|
10
|
+
this.hooks.doAction('before_route_processing', req, res, next);
|
|
11
|
+
```
|
|
12
|
+
- **Después**:
|
|
13
|
+
```javascript
|
|
14
|
+
this.hooks.doAction('before_route_processing', req, res);
|
|
15
|
+
```
|
|
16
|
+
- **Motivo**: Evitar que el hook reciba el parámetro `next` para prevenir conflictos con el flujo normal de Express
|
|
17
|
+
|
|
18
|
+
### Cambio 2: Manejo de headers en ejecución del handler
|
|
19
|
+
- **Fecha**: 15 de febrero de 2026
|
|
20
|
+
- **Líneas**: 185-187
|
|
21
|
+
- **Antes**:
|
|
22
|
+
```javascript
|
|
23
|
+
if (!res.headersSent) {
|
|
24
|
+
matchedRoute.route.handler(req, res, next);
|
|
25
|
+
} else {
|
|
26
|
+
console.warn('Headers ya fueron enviados, no se puede ejecutar el handler');
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
- **Después**:
|
|
30
|
+
```javascript
|
|
31
|
+
if (!res.headersSent) {
|
|
32
|
+
// Añadir logging para depuración
|
|
33
|
+
console.log(`Ejecutando handler para ruta: ${req.method} ${req.url}`);
|
|
34
|
+
matchedRoute.route.handler(req, res, next);
|
|
35
|
+
} else {
|
|
36
|
+
console.warn('Headers ya fueron enviados, no se puede ejecutar el handler');
|
|
37
|
+
next();
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
- **Motivo**: Añadir logging para depuración y asegurar que se llame a `next()` si los headers ya han sido enviados
|
|
41
|
+
|
|
42
|
+
### Cambio 3: Llamada a hooks de handler
|
|
43
|
+
- **Fecha**: 15 de febrero de 2026
|
|
44
|
+
- **Línea(s)**: 180
|
|
45
|
+
- **Antes**:
|
|
46
|
+
```javascript
|
|
47
|
+
this.hooks.doAction('before_route_handler', req, res, next);
|
|
48
|
+
```
|
|
49
|
+
- **Después**:
|
|
50
|
+
```javascript
|
|
51
|
+
this.hooks.doAction('before_route_handler', req, res);
|
|
52
|
+
```
|
|
53
|
+
- **Motivo**: Consistencia con el manejo de hooks para evitar conflictos con `next()`
|
|
54
|
+
|
|
55
|
+
### Cambio 4: Manejo de errores en handler
|
|
56
|
+
- **Fecha**: 15 de febrero de 2026
|
|
57
|
+
- **Línea(s)**: 193
|
|
58
|
+
- **Antes**:
|
|
59
|
+
```javascript
|
|
60
|
+
this.hooks.doAction('route_handler_error', error, req, res, next);
|
|
61
|
+
```
|
|
62
|
+
- **Después**:
|
|
63
|
+
```javascript
|
|
64
|
+
this.hooks.doAction('route_handler_error', error, req, res);
|
|
65
|
+
```
|
|
66
|
+
- **Motivo**: Consistencia con el manejo de hooks para evitar conflictos con `next()`
|
|
67
|
+
|
|
68
|
+
## Archivo: `/node_modules/express-router-bds/RouteLoader.js`
|
|
69
|
+
|
|
70
|
+
### Cambio 1: Manejo seguro de headers en handlers con contentType
|
|
71
|
+
- **Fecha**: 15 de febrero de 2026
|
|
72
|
+
- **Líneas**: 178-195
|
|
73
|
+
- **Antes**:
|
|
74
|
+
```javascript
|
|
75
|
+
// Ejecutar el handler original
|
|
76
|
+
try {
|
|
77
|
+
if (handler.constructor.name === 'AsyncFunction') {
|
|
78
|
+
await handler(req, res, next);
|
|
79
|
+
} else {
|
|
80
|
+
handler(req, res, next);
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
// Si ocurre un error, asegurarse de no intentar enviar headers otra vez
|
|
84
|
+
if (!res.headersSent) {
|
|
85
|
+
next(error);
|
|
86
|
+
} else {
|
|
87
|
+
console.error('Error en el handler:', error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
- **Después**:
|
|
92
|
+
```javascript
|
|
93
|
+
// Ejecutar el handler original solo si no se han enviado headers aún
|
|
94
|
+
if (!res.headersSent) {
|
|
95
|
+
try {
|
|
96
|
+
if (handler.constructor.name === 'AsyncFunction') {
|
|
97
|
+
await handler(req, res, next);
|
|
98
|
+
} else {
|
|
99
|
+
handler(req, res, next);
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
// Si ocurre un error, asegurarse de no intentar enviar headers otra vez
|
|
103
|
+
if (!res.headersSent) {
|
|
104
|
+
next(error);
|
|
105
|
+
} else {
|
|
106
|
+
console.error('Error en el handler:', error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
- **Motivo**: Asegurar que los handlers no se ejecuten si los headers ya han sido enviados
|
|
112
|
+
|
|
113
|
+
### Cambio 2: Eliminación de wrapper adicional
|
|
114
|
+
- **Fecha**: 15 de febrero de 2026
|
|
115
|
+
- **Líneas**: 197-217
|
|
116
|
+
- **Antes**:
|
|
117
|
+
```javascript
|
|
118
|
+
// Crear un handler que envuelva completamente la lógica para prevenir doble ejecución
|
|
119
|
+
const wrappedHandler = async (req, res, next) => {
|
|
120
|
+
// Verificar que no se hayan enviado headers aún
|
|
121
|
+
if (res.headersSent) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Ejecutar el handler final
|
|
126
|
+
try {
|
|
127
|
+
await finalHandler(req, res, next);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (!res.headersSent) {
|
|
130
|
+
next(error);
|
|
131
|
+
} else {
|
|
132
|
+
console.error('Error en el handler:', error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Agregar la ruta con el handler envuelto
|
|
138
|
+
routerIntegration.addRoute(route.method, route.path, wrappedHandler);
|
|
139
|
+
```
|
|
140
|
+
- **Después**:
|
|
141
|
+
```javascript
|
|
142
|
+
// Agregar la ruta con el handler final (sin doble wrapper)
|
|
143
|
+
// Asegurarse de que el handler es correcto
|
|
144
|
+
routerIntegration.addRoute(route.method, route.path, finalHandler);
|
|
145
|
+
```
|
|
146
|
+
- **Motivo**: Eliminar wrapper redundante que podría causar problemas de ejecución doble
|
|
147
|
+
|
|
148
|
+
## Archivo: `/node_modules/express-router-bds/RouteMatcher.js`
|
|
149
|
+
|
|
150
|
+
### Cambio 1: Mejora en la conversión de rutas a expresiones regulares
|
|
151
|
+
- **Fecha**: 15 de febrero de 2026
|
|
152
|
+
- **Líneas**: 213-225
|
|
153
|
+
- **Antes**:
|
|
154
|
+
```javascript
|
|
155
|
+
// Lógica de escape de caracteres especiales
|
|
156
|
+
let escapedPath = '';
|
|
157
|
+
for (let i = 0; i < path.length; i++) {
|
|
158
|
+
const char = path[i];
|
|
159
|
+
if (char.match(/[.+?^${}()|[\]\\-]/) && !(i > 0 && path[i-1] === ':')) {
|
|
160
|
+
escapedPath += '\\' + char;
|
|
161
|
+
} else {
|
|
162
|
+
escapedPath += char;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
- **Después**: (Sin cambios, ya que no se modificó este archivo directamente)
|
|
167
|
+
|
|
168
|
+
## Resumen de Impacto
|
|
169
|
+
|
|
170
|
+
Los cambios realizados al core de `express-router-bds` se enfocaron principalmente en:
|
|
171
|
+
|
|
172
|
+
1. **Evitar conflictos con el parámetro `next`** en las llamadas a hooks
|
|
173
|
+
2. **Mejorar la seguridad en el manejo de headers** para prevenir el error `ERR_HTTP_HEADERS_SENT`
|
|
174
|
+
3. **Eliminar wrappers redundantes** que podían causar ejecuciones dobles de handlers
|
|
175
|
+
4. **Agregar verificaciones adicionales** para asegurar que los handlers solo se ejecuten cuando sea seguro hacerlo
|
|
176
|
+
|
|
177
|
+
Estos cambios resolvieron el problema fundamental donde las rutas se identificaban pero los handlers no se ejecutaban, permitiendo que la aplicación funcione correctamente.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// controllers/mainController.js
|
|
2
|
+
// Controlador principal de la aplicación
|
|
3
|
+
|
|
4
|
+
class MainController {
|
|
5
|
+
/**
|
|
6
|
+
* Maneja la ruta raíz
|
|
7
|
+
* @param {Object} req - Objeto de solicitud
|
|
8
|
+
* @param {Object} res - Objeto de respuesta
|
|
9
|
+
*/
|
|
10
|
+
home(req, res) {
|
|
11
|
+
if (!res.headersSent) {
|
|
12
|
+
res.json({
|
|
13
|
+
message: '¡Bienvenido a la aplicación Express con Router-BDS!',
|
|
14
|
+
timestamp: new Date().toISOString()
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
console.log('Headers ya fueron enviados en home handler');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Maneja la ruta de inicialización
|
|
23
|
+
* @param {Object} req - Objeto de solicitud
|
|
24
|
+
* @param {Object} res - Objeto de respuesta
|
|
25
|
+
*/
|
|
26
|
+
init(req, res) {
|
|
27
|
+
res.json({
|
|
28
|
+
message: 'Aplicación inicializada correctamente con Router-BDS',
|
|
29
|
+
status: 'success'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Obtiene el estado del sistema de colas
|
|
35
|
+
* @param {Object} req - Objeto de solicitud
|
|
36
|
+
* @param {Object} res - Objeto de respuesta
|
|
37
|
+
*/
|
|
38
|
+
getQueueStatus(req, res) {
|
|
39
|
+
const status = req.getQueueStatus();
|
|
40
|
+
res.json(status);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Inicia el sistema de colas
|
|
45
|
+
* @param {Object} req - Objeto de solicitud
|
|
46
|
+
* @param {Object} res - Objeto de respuesta
|
|
47
|
+
*/
|
|
48
|
+
startQueues(req, res) {
|
|
49
|
+
req.queueSystem.start();
|
|
50
|
+
res.json({ message: 'Sistema de colas iniciado' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Detiene el sistema de colas
|
|
55
|
+
* @param {Object} req - Objeto de solicitud
|
|
56
|
+
* @param {Object} res - Objeto de respuesta
|
|
57
|
+
*/
|
|
58
|
+
stopQueues(req, res) {
|
|
59
|
+
req.queueSystem.stop();
|
|
60
|
+
res.json({ message: 'Sistema de colas detenido' });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Agrega una tarea de envío de correo a la cola
|
|
65
|
+
* @param {Object} req - Objeto de solicitud
|
|
66
|
+
* @param {Object} res - Objeto de respuesta
|
|
67
|
+
*/
|
|
68
|
+
sendEmailInQueue(req, res) {
|
|
69
|
+
const { to, subject, content } = req.body;
|
|
70
|
+
|
|
71
|
+
if (!to) {
|
|
72
|
+
return res.status(400).json({ error: 'to es requerido' });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const taskId = req.addTask('envio-correos', async (data, taskObj) => {
|
|
76
|
+
console.log(`[ENVIO-CORREO] Enviando correo a: ${data.to}`);
|
|
77
|
+
|
|
78
|
+
// Simular envío de correo (con 10% de probabilidad de fallo)
|
|
79
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
80
|
+
|
|
81
|
+
if (Math.random() < 0.1) {
|
|
82
|
+
throw new Error(`Fallo al enviar correo a: ${data.to}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log(`[ENVIO-CORREO] Correo enviado exitosamente a: ${data.to}`);
|
|
86
|
+
return `Correo enviado a ${data.to} exitosamente`;
|
|
87
|
+
}, { to, subject, content });
|
|
88
|
+
|
|
89
|
+
res.json({
|
|
90
|
+
message: 'Tarea de envío de correo agregada a la cola',
|
|
91
|
+
taskId
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = new MainController();
|