jerkjs 2.5.8 → 2.6.1
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/CHANGELOG.md +162 -99
- package/README.md +113 -190
- package/RESULTADOS_WAF.md +63 -0
- package/doc-2.5/MANUAL_MODULOS_ADMIN.md +287 -0
- package/doc-2.5/QUEUE_CLI_MODULE_MANUAL.md +289 -0
- package/doc-2.5/QUEUE_SYSTEM_MANUAL.md +320 -0
- package/doc-2.5/ROUTE_CACHE_MODULE_MANUAL.md +205 -0
- package/doc-2.5/WAF_MODULE_MANUAL.md +229 -0
- package/index.js +12 -3
- package/jerk-admin-client/README.md +69 -0
- package/jerk-admin-client/package.json +23 -0
- package/jerk-admin-client.js +257 -0
- package/lib/admin/AdminExtension.js +74 -19
- package/lib/admin/modules/ControllerGeneratorModule.js +414 -0
- package/lib/admin/modules/QueueManagementModule.js +265 -0
- package/lib/admin/modules/RouteCacheModule.js +227 -0
- package/lib/admin/modules/RouteManagerModule.js +468 -0
- package/lib/admin/modules/STATS_MODULE_README.md +15 -0
- package/lib/admin/modules/ViewCacheStatsModule.js +92 -0
- package/lib/admin/modules/WAFModule.js +737 -0
- package/lib/core/server.js +72 -69
- package/lib/middleware/firewall.js +112 -17
- package/lib/mvc/viewEngine.js +69 -10
- package/lib/queue/GlobalQueueStorage.js +38 -0
- package/lib/queue/QueueSystem.js +451 -0
- package/lib/queue/admin_example.js +114 -0
- package/lib/queue/example.js +268 -0
- package/lib/queue/integration.js +109 -0
- package/lib/utils/globalViewCacheInfo.js +16 -0
- package/lib/utils/globalWAFStats.js +54 -0
- package/package.json +2 -2
- package/test-colors.js +46 -0
- package/test-help-alias.js +31 -0
- package/ESTADISTICAS_RENDIMIENTO.md +0 -106
- package/debug_hook.js +0 -11
- package/docs/CACHE_SYSTEM_MAP.md +0 -206
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Gestión de Rutas para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para crear y deshabilitar rutas de manera interactiva
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class RouteManagerModule {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor del módulo de gestión de rutas
|
|
12
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
13
|
+
*/
|
|
14
|
+
constructor(adminExtension) {
|
|
15
|
+
this.adminExtension = adminExtension;
|
|
16
|
+
this.name = 'Route Manager Module';
|
|
17
|
+
this.description = 'Módulo para crear y deshabilitar rutas de manera interactiva';
|
|
18
|
+
this.commands = ['manage-routes', 'route-manager', 'route-mgmt'];
|
|
19
|
+
|
|
20
|
+
// Estado para el proceso interactivo
|
|
21
|
+
this.currentProcess = new Map(); // Almacena el estado de gestión por socket
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Manejador para los comandos del módulo de gestión de rutas
|
|
26
|
+
* @param {string} command - Comando a ejecutar
|
|
27
|
+
* @param {Object} socket - Socket de la conexión
|
|
28
|
+
*/
|
|
29
|
+
handleCommand(command, socket) {
|
|
30
|
+
switch (command) {
|
|
31
|
+
case 'manage-routes':
|
|
32
|
+
case 'route-manager':
|
|
33
|
+
case 'route-mgmt':
|
|
34
|
+
this.startRouteManagement(socket);
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
socket.write(`Comando desconocido para el módulo de gestión de rutas: ${command}\n`);
|
|
38
|
+
socket.write(`Comandos disponibles: manage-routes, route-manager, route-mgmt\n\n`);
|
|
39
|
+
socket.write(`> `);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Inicia el proceso interactivo de gestión de rutas
|
|
45
|
+
* @param {Object} socket - Socket de la conexión
|
|
46
|
+
*/
|
|
47
|
+
startRouteManagement(socket) {
|
|
48
|
+
const sessionId = this.getSessionId(socket);
|
|
49
|
+
|
|
50
|
+
// Inicializar el estado de la sesión
|
|
51
|
+
this.currentProcess.set(sessionId, {
|
|
52
|
+
step: 'action',
|
|
53
|
+
routeData: {}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
socket.write('\n=== Gestión de Rutas ===\n');
|
|
57
|
+
socket.write('¿Qué deseas hacer?\n');
|
|
58
|
+
socket.write('1. Crear nueva ruta\n');
|
|
59
|
+
socket.write('2. Deshabilitar ruta existente\n');
|
|
60
|
+
socket.write('3. Ver rutas registradas\n');
|
|
61
|
+
socket.write('4. Ver rutas activas\n');
|
|
62
|
+
socket.write('\nEscribe el número de la opción (1-4) o "cancel" para cancelar:\n> ');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Obtiene un ID único para la sesión del socket
|
|
67
|
+
* @param {Object} socket - Socket de la conexión
|
|
68
|
+
* @returns {string} - ID de sesión
|
|
69
|
+
*/
|
|
70
|
+
getSessionId(socket) {
|
|
71
|
+
// Usar la dirección remota y puerto como identificador único
|
|
72
|
+
return `${socket.remoteAddress}:${socket.remotePort}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Procesa la entrada del usuario durante el proceso interactivo
|
|
77
|
+
* @param {Object} socket - Socket de la conexión
|
|
78
|
+
* @param {string} input - Entrada del usuario
|
|
79
|
+
*/
|
|
80
|
+
processInput(socket, input) {
|
|
81
|
+
const sessionId = this.getSessionId(socket);
|
|
82
|
+
const processState = this.currentProcess.get(sessionId);
|
|
83
|
+
|
|
84
|
+
if (!processState) {
|
|
85
|
+
socket.write('No hay proceso activo. Usa "manage-routes" para iniciar.\n> ');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const userInput = input.trim();
|
|
90
|
+
|
|
91
|
+
if (userInput.toLowerCase() === 'cancel') {
|
|
92
|
+
this.cancelProcess(socket, sessionId);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
switch (processState.step) {
|
|
97
|
+
case 'action':
|
|
98
|
+
this.handleActionSelection(socket, sessionId, userInput);
|
|
99
|
+
break;
|
|
100
|
+
case 'create_method':
|
|
101
|
+
this.handleCreateMethod(socket, sessionId, userInput);
|
|
102
|
+
break;
|
|
103
|
+
case 'create_path':
|
|
104
|
+
this.handleCreatePath(socket, sessionId, userInput);
|
|
105
|
+
break;
|
|
106
|
+
case 'create_controller':
|
|
107
|
+
this.handleCreateController(socket, sessionId, userInput);
|
|
108
|
+
break;
|
|
109
|
+
case 'create_handler':
|
|
110
|
+
this.handleCreateHandler(socket, sessionId, userInput);
|
|
111
|
+
break;
|
|
112
|
+
case 'create_confirm':
|
|
113
|
+
this.handleCreateConfirmation(socket, sessionId, userInput);
|
|
114
|
+
break;
|
|
115
|
+
case 'disable_select':
|
|
116
|
+
this.handleDisableSelection(socket, sessionId, userInput);
|
|
117
|
+
break;
|
|
118
|
+
case 'disable_confirm':
|
|
119
|
+
this.handleDisableConfirmation(socket, sessionId, userInput);
|
|
120
|
+
break;
|
|
121
|
+
case 'view_routes':
|
|
122
|
+
if (userInput.toLowerCase() === 'sí' || userInput.toLowerCase() === 'si' || userInput.toLowerCase() === 'yes') {
|
|
123
|
+
this.showRegisteredRoutes(socket);
|
|
124
|
+
} else {
|
|
125
|
+
socket.write('\nVolviendo al menú principal...\n> ');
|
|
126
|
+
this.resetProcess(socket);
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Maneja la selección de acción (crear, deshabilitar, ver rutas)
|
|
134
|
+
* @param {Object} socket - Socket de la conexión
|
|
135
|
+
* @param {string} sessionId - ID de la sesión
|
|
136
|
+
* @param {string} selection - Selección del usuario
|
|
137
|
+
*/
|
|
138
|
+
handleActionSelection(socket, sessionId, selection) {
|
|
139
|
+
const processState = this.currentProcess.get(sessionId);
|
|
140
|
+
|
|
141
|
+
switch (selection) {
|
|
142
|
+
case '1':
|
|
143
|
+
processState.step = 'create_method';
|
|
144
|
+
processState.action = 'create';
|
|
145
|
+
socket.write('\n=== Crear Nueva Ruta ===\n');
|
|
146
|
+
socket.write('Selecciona el método HTTP:\n');
|
|
147
|
+
socket.write('1. GET\n2. POST\n3. PUT\n4. DELETE\n5. PATCH\n6. Otro\n');
|
|
148
|
+
socket.write('Escribe el número o el método directamente (GET, POST, etc.):\n> ');
|
|
149
|
+
break;
|
|
150
|
+
case '2':
|
|
151
|
+
processState.step = 'disable_select';
|
|
152
|
+
processState.action = 'disable';
|
|
153
|
+
this.listAvailableRoutes(socket);
|
|
154
|
+
break;
|
|
155
|
+
case '3':
|
|
156
|
+
this.showRegisteredRoutes(socket);
|
|
157
|
+
this.resetProcess(socket);
|
|
158
|
+
break;
|
|
159
|
+
case '4':
|
|
160
|
+
this.showActiveRoutes(socket);
|
|
161
|
+
this.resetProcess(socket);
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
socket.write('Opción inválida. Por favor, selecciona 1, 2, 3 o 4:\n> ');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Muestra las rutas registradas
|
|
170
|
+
* @param {Object} socket - Socket de la conexión
|
|
171
|
+
*/
|
|
172
|
+
showRegisteredRoutes(socket) {
|
|
173
|
+
if (this.adminExtension.registeredRoutes && this.adminExtension.registeredRoutes.length > 0) {
|
|
174
|
+
socket.write('\n=== Rutas Registradas ===\n');
|
|
175
|
+
this.adminExtension.registeredRoutes.forEach((route, index) => {
|
|
176
|
+
socket.write(`${index + 1}. ${route.method} ${route.path}\n`);
|
|
177
|
+
});
|
|
178
|
+
} else {
|
|
179
|
+
socket.write('\n=== Rutas Registradas ===\n');
|
|
180
|
+
socket.write('No hay rutas registradas.\n');
|
|
181
|
+
}
|
|
182
|
+
socket.write('\n> ');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Muestra las rutas activas
|
|
187
|
+
* @param {Object} socket - Socket de la conexión
|
|
188
|
+
*/
|
|
189
|
+
showActiveRoutes(socket) {
|
|
190
|
+
if (this.adminExtension.activeRoutes && this.adminExtension.activeRoutes.size > 0) {
|
|
191
|
+
socket.write('\n=== Rutas Activas ===\n');
|
|
192
|
+
for (const [url, info] of this.adminExtension.activeRoutes) {
|
|
193
|
+
socket.write(`${info.method} ${url} - ${info.timestamp} (${info.remoteAddress})\n`);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
socket.write('\n=== Rutas Activas ===\n');
|
|
197
|
+
socket.write('No hay rutas activas registradas.\n');
|
|
198
|
+
}
|
|
199
|
+
socket.write('\n> ');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Lista las rutas disponibles para deshabilitar
|
|
204
|
+
* @param {Object} socket - Socket de la conexión
|
|
205
|
+
*/
|
|
206
|
+
listAvailableRoutes(socket) {
|
|
207
|
+
if (this.adminExtension.registeredRoutes && this.adminExtension.registeredRoutes.length > 0) {
|
|
208
|
+
socket.write('\n=== Rutas Disponibles para Deshabilitar ===\n');
|
|
209
|
+
this.adminExtension.registeredRoutes.forEach((route, index) => {
|
|
210
|
+
socket.write(`${index + 1}. ${route.method} ${route.path}\n`);
|
|
211
|
+
});
|
|
212
|
+
socket.write('\nSelecciona el número de la ruta que deseas deshabilitar:\n> ');
|
|
213
|
+
} else {
|
|
214
|
+
socket.write('\nNo hay rutas registradas para deshabilitar.\n');
|
|
215
|
+
socket.write('Volviendo al menú principal...\n> ');
|
|
216
|
+
this.resetProcess(socket);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Maneja la selección del método HTTP para crear ruta
|
|
222
|
+
* @param {Object} socket - Socket de la conexión
|
|
223
|
+
* @param {string} sessionId - ID de la sesión
|
|
224
|
+
* @param {string} method - Método HTTP seleccionado
|
|
225
|
+
*/
|
|
226
|
+
handleCreateMethod(socket, sessionId, method) {
|
|
227
|
+
const processState = this.currentProcess.get(sessionId);
|
|
228
|
+
const methodMap = {
|
|
229
|
+
'1': 'GET', '2': 'POST', '3': 'PUT', '4': 'DELETE', '5': 'PATCH', '6': 'OTHER'
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
let selectedMethod;
|
|
233
|
+
if (methodMap[method]) {
|
|
234
|
+
selectedMethod = methodMap[method];
|
|
235
|
+
if (selectedMethod === 'OTHER') {
|
|
236
|
+
socket.write('Escribe el método HTTP personalizado:\n> ');
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
selectedMethod = method.toUpperCase();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
processState.routeData.method = selectedMethod;
|
|
244
|
+
processState.step = 'create_path';
|
|
245
|
+
|
|
246
|
+
socket.write(`\nMétodo seleccionado: ${selectedMethod}\n`);
|
|
247
|
+
socket.write('Introduce la ruta (ej: /api/users, /users/:id):\n> ');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Maneja la introducción de la ruta
|
|
252
|
+
* @param {Object} socket - Socket de la conexión
|
|
253
|
+
* @param {string} sessionId - ID de la sesión
|
|
254
|
+
* @param {string} routePath - Ruta introducida
|
|
255
|
+
*/
|
|
256
|
+
handleCreatePath(socket, sessionId, routePath) {
|
|
257
|
+
const processState = this.currentProcess.get(sessionId);
|
|
258
|
+
|
|
259
|
+
if (!routePath || !routePath.startsWith('/')) {
|
|
260
|
+
socket.write('La ruta debe comenzar con "/". Por favor, introduce una ruta válida:\n> ');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
processState.routeData.path = routePath;
|
|
265
|
+
processState.step = 'create_controller';
|
|
266
|
+
|
|
267
|
+
socket.write(`\nRuta: ${routePath}\n`);
|
|
268
|
+
socket.write('Introduce la ruta al archivo del controlador (ej: ./controllers/UserController.js):\n> ');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Maneja la introducción del controlador
|
|
273
|
+
* @param {Object} socket - Socket de la conexión
|
|
274
|
+
* @param {string} sessionId - ID de la sesión
|
|
275
|
+
* @param {string} controller - Ruta al controlador
|
|
276
|
+
*/
|
|
277
|
+
handleCreateController(socket, sessionId, controller) {
|
|
278
|
+
const processState = this.currentProcess.get(sessionId);
|
|
279
|
+
|
|
280
|
+
if (!controller) {
|
|
281
|
+
socket.write('La ruta al controlador no puede estar vacía. Por favor, introduce una ruta válida:\n> ');
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
processState.routeData.controller = controller;
|
|
286
|
+
processState.step = 'create_handler';
|
|
287
|
+
|
|
288
|
+
socket.write(`\nControlador: ${controller}\n`);
|
|
289
|
+
socket.write('Introduce el nombre del método del controlador (ej: index, show, create):\n> ');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Maneja la introducción del handler
|
|
294
|
+
* @param {Object} socket - Socket de la conexión
|
|
295
|
+
* @param {string} sessionId - ID de la sesión
|
|
296
|
+
* @param {string} handler - Nombre del handler
|
|
297
|
+
*/
|
|
298
|
+
handleCreateHandler(socket, sessionId, handler) {
|
|
299
|
+
const processState = this.currentProcess.get(sessionId);
|
|
300
|
+
|
|
301
|
+
if (!handler) {
|
|
302
|
+
socket.write('El nombre del handler no puede estar vacío. Por favor, introduce un nombre válido:\n> ');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
processState.routeData.handler = handler;
|
|
307
|
+
processState.step = 'create_confirm';
|
|
308
|
+
|
|
309
|
+
socket.write(`\nHandler: ${handler}\n`);
|
|
310
|
+
this.showRoutePreview(socket, processState.routeData);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Muestra una vista previa de la ruta que se va a crear
|
|
315
|
+
* @param {Object} socket - Socket de la conexión
|
|
316
|
+
* @param {Object} routeData - Datos de la ruta
|
|
317
|
+
*/
|
|
318
|
+
showRoutePreview(socket, routeData) {
|
|
319
|
+
socket.write('\n=== Vista Previa de la Ruta ===\n');
|
|
320
|
+
socket.write(`Método: ${routeData.method}\n`);
|
|
321
|
+
socket.write(`Ruta: ${routeData.path}\n`);
|
|
322
|
+
socket.write(`Controlador: ${routeData.controller}\n`);
|
|
323
|
+
socket.write(`Handler: ${routeData.handler}\n\n`);
|
|
324
|
+
|
|
325
|
+
const routeEntry = {
|
|
326
|
+
path: routeData.path,
|
|
327
|
+
method: routeData.method,
|
|
328
|
+
controller: routeData.controller,
|
|
329
|
+
handler: routeData.handler,
|
|
330
|
+
contentType: "application/json"
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
socket.write('Entrada para routes.json:\n');
|
|
334
|
+
socket.write(JSON.stringify(routeEntry, null, 2) + '\n\n');
|
|
335
|
+
|
|
336
|
+
socket.write('¿Deseas crear esta ruta? (sí/no):\n> ');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Maneja la confirmación de creación de ruta
|
|
341
|
+
* @param {Object} socket - Socket de la conexión
|
|
342
|
+
* @param {string} sessionId - ID de la sesión
|
|
343
|
+
* @param {string} confirmation - Confirmación del usuario
|
|
344
|
+
*/
|
|
345
|
+
handleCreateConfirmation(socket, sessionId, confirmation) {
|
|
346
|
+
const processState = this.currentProcess.get(sessionId);
|
|
347
|
+
|
|
348
|
+
if (confirmation.toLowerCase() === 'sí' || confirmation.toLowerCase() === 'si' || confirmation.toLowerCase() === 'yes') {
|
|
349
|
+
this.createRoute(socket, processState.routeData);
|
|
350
|
+
} else {
|
|
351
|
+
socket.write('\nCreación de ruta cancelada.\n> ');
|
|
352
|
+
this.resetProcess(socket);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Crea la ruta en el sistema
|
|
358
|
+
* @param {Object} socket - Socket de la conexión
|
|
359
|
+
* @param {Object} routeData - Datos de la ruta
|
|
360
|
+
*/
|
|
361
|
+
createRoute(socket, routeData) {
|
|
362
|
+
// En un entorno real, aquí se agregaría la ruta al servidor
|
|
363
|
+
// Por ahora, solo mostramos un mensaje de confirmación
|
|
364
|
+
|
|
365
|
+
socket.write(`\n✅ Ruta "${routeData.method} ${routeData.path}" creada exitosamente.\n`);
|
|
366
|
+
socket.write(`- Controlador: ${routeData.controller}\n`);
|
|
367
|
+
socket.write(`- Handler: ${routeData.handler}\n`);
|
|
368
|
+
|
|
369
|
+
// Agregar a las rutas registradas
|
|
370
|
+
if (this.adminExtension.registeredRoutes) {
|
|
371
|
+
const newRoute = {
|
|
372
|
+
method: routeData.method,
|
|
373
|
+
path: routeData.path,
|
|
374
|
+
controller: routeData.controller,
|
|
375
|
+
handler: routeData.handler
|
|
376
|
+
};
|
|
377
|
+
this.adminExtension.registeredRoutes.push(newRoute);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
socket.write('\n> ');
|
|
381
|
+
this.resetProcess(socket);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Maneja la selección de ruta para deshabilitar
|
|
386
|
+
* @param {Object} socket - Socket de la conexión
|
|
387
|
+
* @param {string} sessionId - ID de la sesión
|
|
388
|
+
* @param {string} selection - Selección del usuario
|
|
389
|
+
*/
|
|
390
|
+
handleDisableSelection(socket, sessionId, selection) {
|
|
391
|
+
const processState = this.currentProcess.get(sessionId);
|
|
392
|
+
|
|
393
|
+
const routeIndex = parseInt(selection) - 1;
|
|
394
|
+
|
|
395
|
+
if (isNaN(routeIndex) || routeIndex < 0 || routeIndex >= this.adminExtension.registeredRoutes.length) {
|
|
396
|
+
socket.write('Número de ruta inválido. Por favor, selecciona un número válido:\n> ');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
processState.routeToDisable = this.adminExtension.registeredRoutes[routeIndex];
|
|
401
|
+
processState.step = 'disable_confirm';
|
|
402
|
+
|
|
403
|
+
socket.write(`\nRuta seleccionada para deshabilitar:\n`);
|
|
404
|
+
socket.write(`${processState.routeToDisable.method} ${processState.routeToDisable.path}\n`);
|
|
405
|
+
socket.write(`¿Estás seguro de que deseas deshabilitar esta ruta? (sí/no):\n> `);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Maneja la confirmación de deshabilitación de ruta
|
|
410
|
+
* @param {Object} socket - Socket de la conexión
|
|
411
|
+
* @param {string} sessionId - ID de la sesión
|
|
412
|
+
* @param {string} confirmation - Confirmación del usuario
|
|
413
|
+
*/
|
|
414
|
+
handleDisableConfirmation(socket, sessionId, confirmation) {
|
|
415
|
+
const processState = this.currentProcess.get(sessionId);
|
|
416
|
+
|
|
417
|
+
if (confirmation.toLowerCase() === 'sí' || confirmation.toLowerCase() === 'si' || confirmation.toLowerCase() === 'yes') {
|
|
418
|
+
this.disableRoute(socket, processState.routeToDisable);
|
|
419
|
+
} else {
|
|
420
|
+
socket.write('\nDeshabilitación de ruta cancelada.\n> ');
|
|
421
|
+
this.resetProcess(socket);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Deshabilita la ruta del sistema
|
|
427
|
+
* @param {Object} socket - Socket de la conexión
|
|
428
|
+
* @param {Object} route - Ruta a deshabilitar
|
|
429
|
+
*/
|
|
430
|
+
disableRoute(socket, route) {
|
|
431
|
+
// En un entorno real, aquí se removería la ruta del servidor
|
|
432
|
+
// Por ahora, solo mostramos un mensaje de confirmación
|
|
433
|
+
|
|
434
|
+
socket.write(`\n✅ Ruta "${route.method} ${route.path}" deshabilitada exitosamente.\n`);
|
|
435
|
+
|
|
436
|
+
// Remover de las rutas registradas
|
|
437
|
+
if (this.adminExtension.registeredRoutes) {
|
|
438
|
+
const index = this.adminExtension.registeredRoutes.indexOf(route);
|
|
439
|
+
if (index !== -1) {
|
|
440
|
+
this.adminExtension.registeredRoutes.splice(index, 1);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
socket.write('\n> ');
|
|
445
|
+
this.resetProcess(socket);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Reinicia el proceso de gestión de rutas
|
|
450
|
+
* @param {Object} socket - Socket de la conexión
|
|
451
|
+
*/
|
|
452
|
+
resetProcess(socket) {
|
|
453
|
+
const sessionId = this.getSessionId(socket);
|
|
454
|
+
this.currentProcess.delete(sessionId);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Cancela el proceso de gestión de rutas
|
|
459
|
+
* @param {Object} socket - Socket de la conexión
|
|
460
|
+
* @param {string} sessionId - ID de la sesión
|
|
461
|
+
*/
|
|
462
|
+
cancelProcess(socket, sessionId) {
|
|
463
|
+
this.currentProcess.delete(sessionId);
|
|
464
|
+
socket.write('\nProceso cancelado.\n> ');
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
module.exports = RouteManagerModule;
|
|
@@ -63,6 +63,21 @@ Las estadísticas se actualizan directamente en el servidor en los siguientes pu
|
|
|
63
63
|
- Al enviar la respuesta: actualiza `responseBytes`
|
|
64
64
|
- Al procesar una ruta: actualiza `requestsProcessed`, `responsesSent`, `routeAccesses`, `endpointHits`
|
|
65
65
|
|
|
66
|
+
## Sistema de Caché de Vistas
|
|
67
|
+
|
|
68
|
+
Además del sistema de estadísticas general, el framework también incluye un sistema de caché de vistas con estadísticas globales:
|
|
69
|
+
|
|
70
|
+
- `globalViewCacheInfo.viewCache`: Mapa de vistas en caché
|
|
71
|
+
- `globalViewCacheInfo.cacheStats`: Estadísticas de hits/misses
|
|
72
|
+
- `globalViewCacheInfo.viewDependencies`: Registro de dependencias entre vistas (inclusiones)
|
|
73
|
+
|
|
74
|
+
### Estadísticas del Caché de Vistas
|
|
75
|
+
|
|
76
|
+
- Hits: Número de accesos exitosos al caché
|
|
77
|
+
- Misses: Número de veces que se leyó desde disco
|
|
78
|
+
- Tasa de aciertos: Porcentaje de accesos exitosos
|
|
79
|
+
- Dependencias: Registro de inclusiones entre vistas
|
|
80
|
+
|
|
66
81
|
## Instalación
|
|
67
82
|
|
|
68
83
|
El módulo se carga automáticamente cuando se inicializa la extensión de administración, ya que está ubicado en el directorio `modules` de la extensión.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Estadísticas del Caché de Vistas para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para mostrar estadísticas del caché de vistas
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class ViewCacheStatsModule {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del módulo de estadísticas del caché de vistas
|
|
9
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
10
|
+
*/
|
|
11
|
+
constructor(adminExtension) {
|
|
12
|
+
this.adminExtension = adminExtension;
|
|
13
|
+
this.name = 'View Cache Statistics Module';
|
|
14
|
+
this.description = 'Módulo para mostrar estadísticas del caché de vistas';
|
|
15
|
+
this.commands = ['view-cache'];
|
|
16
|
+
|
|
17
|
+
// Cargar el objeto global de estadísticas del caché de vistas
|
|
18
|
+
this.globalViewCacheInfo = require('../../utils/globalViewCacheInfo').globalViewCacheInfo;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Manejador para los comandos del módulo de estadísticas del caché de vistas
|
|
23
|
+
* @param {string} command - Comando a ejecutar
|
|
24
|
+
* @param {Object} socket - Socket de la conexión
|
|
25
|
+
*/
|
|
26
|
+
handleCommand(command, socket) {
|
|
27
|
+
switch (command) {
|
|
28
|
+
case 'view-cache':
|
|
29
|
+
case 'vcache':
|
|
30
|
+
case 'view-stats':
|
|
31
|
+
this.showViewCacheStats(socket);
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
socket.write(`Comando desconocido para el módulo de estadísticas del caché de vistas: ${command}\n`);
|
|
35
|
+
socket.write(`Comandos disponibles: view-cache, vcache, view-stats\n\n`);
|
|
36
|
+
socket.write(`> `);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Muestra estadísticas del caché de vistas
|
|
42
|
+
* @param {Object} socket - Socket de la conexión
|
|
43
|
+
*/
|
|
44
|
+
showViewCacheStats(socket) {
|
|
45
|
+
const { cacheStats, viewCache, viewDependencies } = this.globalViewCacheInfo;
|
|
46
|
+
|
|
47
|
+
// Codigos de color ANSI
|
|
48
|
+
const RESET = '\x1b[0m';
|
|
49
|
+
const BOLD = '\x1b[1m';
|
|
50
|
+
const GREEN = '\x1b[32m';
|
|
51
|
+
const YELLOW = '\x1b[33m';
|
|
52
|
+
const BLUE = '\x1b[34m';
|
|
53
|
+
const CYAN = '\x1b[36m';
|
|
54
|
+
const MAGENTA = '\x1b[35m';
|
|
55
|
+
|
|
56
|
+
socket.write(`\n${BOLD}${CYAN}=== Estadísticas del Caché de Vistas ===${RESET}\n`);
|
|
57
|
+
socket.write(`${GREEN}Vistas en caché:${RESET} ${viewCache.size}\n`);
|
|
58
|
+
socket.write(`${YELLOW}Hits (accesos exitosos):${RESET} ${cacheStats.hits}\n`);
|
|
59
|
+
socket.write(`${YELLOW}Misses (cargas desde disco):${RESET} ${cacheStats.misses}\n`);
|
|
60
|
+
socket.write(`${GREEN}Total de vistas únicas:${RESET} ${cacheStats.totalViews}\n`);
|
|
61
|
+
|
|
62
|
+
if (cacheStats.hits + cacheStats.misses > 0) {
|
|
63
|
+
const hitRate = (cacheStats.hits / (cacheStats.hits + cacheStats.misses) * 100).toFixed(2);
|
|
64
|
+
socket.write(`${BLUE}Tasa de aciertos:${RESET} ${hitRate}%\n`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Mostrar vistas más usadas (basado en el tamaño del caché)
|
|
68
|
+
if (viewCache.size > 0) {
|
|
69
|
+
socket.write(`\n${BOLD}${MAGENTA}Vistas en caché:${RESET}\n`);
|
|
70
|
+
for (const [viewPath, content] of viewCache) {
|
|
71
|
+
socket.write(` ${viewPath} (${content.length} chars)\n`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Mostrar dependencias de vistas
|
|
76
|
+
if (viewDependencies.size > 0) {
|
|
77
|
+
socket.write(`\n${BOLD}${MAGENTA}Dependencias de vistas (inclusiones):${RESET}\n`);
|
|
78
|
+
for (const [viewPath, dependencies] of viewDependencies) {
|
|
79
|
+
if (dependencies.size > 0) {
|
|
80
|
+
socket.write(` ${viewPath}:\n`);
|
|
81
|
+
for (const dependency of dependencies) {
|
|
82
|
+
socket.write(` - ${dependency}\n`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
socket.write(`\n${RESET}> `);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
module.exports = ViewCacheStatsModule;
|