jerkjs 2.5.6 → 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 +167 -79
- package/README.md +134 -146
- package/RESULTADOS_WAF.md +63 -0
- package/doc-2.5/ADMIN_EXTENSION_COMMANDS_MANUAL.md +261 -0
- package/doc-2.5/ADMIN_EXTENSION_HOOK_EXAMPLE.md +28 -0
- package/doc-2.5/ADMIN_EXTENSION_INTEGRATION_MANUAL.md +232 -0
- package/doc-2.5/CACHE_SYSTEM_MAP.md +206 -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 +19 -4
- 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 +491 -0
- package/lib/admin/ModuleLoader.js +77 -0
- package/lib/admin/config.js +21 -0
- package/lib/admin/modules/CacheModule.js +145 -0
- 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 +113 -0
- package/lib/admin/modules/StatsModule.js +140 -0
- package/lib/admin/modules/SystemModule.js +140 -0
- package/lib/admin/modules/TimeModule.js +95 -0
- package/lib/admin/modules/ViewCacheStatsModule.js +92 -0
- package/lib/admin/modules/WAFModule.js +737 -0
- package/lib/cache/CacheHooks.js +141 -0
- package/lib/core/server.js +223 -77
- package/lib/middleware/firewall.js +112 -17
- package/lib/mvc/viewEngine.js +89 -5
- 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/router/RouteMatcher.js +242 -54
- package/lib/utils/globalStats.js +16 -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
|
@@ -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;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Módulo de Estadísticas para la Extensión de Administración de JERK Framework
|
|
2
|
+
|
|
3
|
+
## Descripción
|
|
4
|
+
|
|
5
|
+
El módulo de estadísticas es una extensión de la extensión de administración de JERK Framework que permite monitorear y visualizar métricas importantes del servidor en tiempo real.
|
|
6
|
+
|
|
7
|
+
## Características
|
|
8
|
+
|
|
9
|
+
- Conteo de solicitudes procesadas y respuestas enviadas
|
|
10
|
+
- Medición del tráfico de entrada y salida en kilobytes
|
|
11
|
+
- Registro de accesos a rutas y endpoints
|
|
12
|
+
- Identificación de endpoints y rutas más accedidas
|
|
13
|
+
- Sistema de estadísticas global para acceso directo y confiable
|
|
14
|
+
|
|
15
|
+
## Comandos Disponibles
|
|
16
|
+
|
|
17
|
+
- `stats` o `statistics`: Muestra estadísticas generales del servidor
|
|
18
|
+
- `requests`: Muestra estadísticas específicas de solicitudes
|
|
19
|
+
- `endpoints`: Muestra estadísticas de endpoints y rutas más accedidas
|
|
20
|
+
|
|
21
|
+
## Métricas Monitorizadas
|
|
22
|
+
|
|
23
|
+
### Estadísticas Generales
|
|
24
|
+
- Solicitudes procesadas totales
|
|
25
|
+
- Cantidad de datos recibidos (en KB)
|
|
26
|
+
- Respuestas enviadas totales
|
|
27
|
+
- Cantidad de datos enviados (en KB)
|
|
28
|
+
- Número de rutas registradas
|
|
29
|
+
- Número de rutas activas
|
|
30
|
+
|
|
31
|
+
### Estadísticas de Solicitudes
|
|
32
|
+
- Total de solicitudes procesadas
|
|
33
|
+
- Total de bytes recibidos
|
|
34
|
+
- Accesos a rutas (Input/Output)
|
|
35
|
+
|
|
36
|
+
### Estadísticas de Endpoints
|
|
37
|
+
- Top 10 endpoints más accedidos
|
|
38
|
+
- Top 10 rutas más accedidas
|
|
39
|
+
|
|
40
|
+
## Sistema de Almacenamiento de Estadísticas
|
|
41
|
+
|
|
42
|
+
A diferencia de enfoques basados en hooks, este módulo utiliza un sistema de almacenamiento global de estadísticas (`globalStats`) que se actualiza directamente en el servidor cuando ocurren eventos, garantizando:
|
|
43
|
+
|
|
44
|
+
- Acceso directo y confiable a las métricas
|
|
45
|
+
- Actualización en tiempo real sin dependencia de hooks
|
|
46
|
+
- Persistencia de datos entre solicitudes
|
|
47
|
+
- Mayor rendimiento y menor latencia
|
|
48
|
+
|
|
49
|
+
### Componentes del Sistema de Estadísticas
|
|
50
|
+
|
|
51
|
+
- `globalStats.requestsProcessed`: Contador de solicitudes procesadas
|
|
52
|
+
- `globalStats.responsesSent`: Contador de respuestas enviadas
|
|
53
|
+
- `globalStats.requestBytes`: Total de bytes recibidos
|
|
54
|
+
- `globalStats.responseBytes`: Total de bytes enviados
|
|
55
|
+
- `globalStats.routeAccesses`: Mapa de accesos a rutas
|
|
56
|
+
- `globalStats.endpointHits`: Mapa de hits a endpoints
|
|
57
|
+
|
|
58
|
+
### Actualización de Estadísticas en el Servidor
|
|
59
|
+
|
|
60
|
+
Las estadísticas se actualizan directamente en el servidor en los siguientes puntos:
|
|
61
|
+
|
|
62
|
+
- Al procesar el cuerpo de la solicitud: actualiza `requestBytes`
|
|
63
|
+
- Al enviar la respuesta: actualiza `responseBytes`
|
|
64
|
+
- Al procesar una ruta: actualiza `requestsProcessed`, `responsesSent`, `routeAccesses`, `endpointHits`
|
|
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
|
+
|
|
81
|
+
## Instalación
|
|
82
|
+
|
|
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.
|
|
84
|
+
|
|
85
|
+
## Uso
|
|
86
|
+
|
|
87
|
+
1. Inicialice la extensión de administración en su servidor:
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
const server = new APIServer({ port: 3000 });
|
|
91
|
+
server.initializeAdminExtension({
|
|
92
|
+
port: 9999,
|
|
93
|
+
host: '127.0.0.1'
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
2. Conéctese al servidor de administración:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
telnet localhost 9999
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
3. Use cualquiera de los comandos disponibles:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
stats
|
|
107
|
+
requests
|
|
108
|
+
endpoints
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Contribución
|
|
112
|
+
|
|
113
|
+
Las contribuciones son bienvenidas. Si desea mejorar este módulo, por favor cree un fork del repositorio y envíe un pull request con sus cambios.
|