jerkjs 2.5.4 → 2.5.8
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/BENCHMARK_RESULTS.md +60 -0
- package/CHANGELOG.md +43 -0
- package/ESTADISTICAS_RENDIMIENTO.md +106 -0
- package/README.md +142 -423
- package/README_LEGACY.md +513 -0
- package/debug_hook.js +11 -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/SESSION_SECURITY_FLAGS.md +174 -0
- package/doc-2.5/an/303/241lisis-completo-jerk-framework.md +213 -0
- package/docs/CACHE_SYSTEM_MAP.md +206 -0
- package/docs/SERVER_OPTIMIZATION_NOTES.md +87 -0
- package/index.js +7 -1
- package/jerk2.5.webp +0 -0
- package/lib/admin/AdminExtension.js +436 -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/STATS_MODULE_README.md +98 -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/cache/CacheHooks.js +141 -0
- package/lib/core/server.js +199 -46
- package/lib/middleware/session.js +11 -3
- package/lib/mvc/viewEngine.js +26 -1
- package/lib/router/RouteMatcher.js +242 -54
- package/lib/utils/globalStats.js +16 -0
- package/package.json +2 -2
- package/@qaLoadModel/controllers/ProductController.js +0 -143
- package/@qaLoadModel/controllers/UserController.js +0 -143
- package/@qaLoadModel/models/ProductModel.js +0 -41
- package/@qaLoadModel/models/UserModel.js +0 -41
- package/@qaLoadModel/package.json +0 -22
- package/@qaLoadModel/qa_report.md +0 -71
- package/@qaLoadModel/results.md +0 -97
- package/@qaLoadModel/routes.json +0 -58
- package/@qaLoadModel/server.js +0 -43
- package/@qaLoadModel/simple-test.js +0 -96
- package/@qaLoadModel/test-models.js +0 -144
- package/@qaLoadModel/test_endpoints.sh +0 -35
- package/@qaLoadModel/test_final.js +0 -89
- package/@qaLoadModel/views/products/index.html +0 -45
- package/@qaLoadModel/views/products/show.html +0 -27
- package/@qaLoadModel/views/users/index.html +0 -44
- package/@qaLoadModel/views/users/show.html +0 -26
- package/qa/INFORME_QA_JERKJS_ROUTING.md +0 -108
- package/qa/informe_qa_fix_enrutamiento.md +0 -93
- package/qa-app/controllers/homeController.js +0 -9
- package/qa-app/controllers/userController.js +0 -76
- package/qa-app/hooks-config.js +0 -65
- package/qa-app/models/UserModel.js +0 -36
- package/qa-app/package-lock.json +0 -1683
- package/qa-app/package.json +0 -25
- package/qa-app/public/css/style.css +0 -15
- package/qa-app/public/images/logo.png +0 -3
- package/qa-app/public/index.html +0 -15
- package/qa-app/public/js/main.js +0 -7
- package/qa-app/routes/api-routes.json +0 -23
- package/qa-app/routes/page-routes.json +0 -16
- package/qa-app/routes/static-routes.json +0 -20
- package/qa-app/server.js +0 -68
- package/qa-app/views/footer.html +0 -3
- package/qa-app/views/index.html +0 -20
- package/qa-app/views/users.html +0 -20
- package/utils/find_file_path.sh +0 -36
- /package/{doc2.5.3 → doc-2.5}/manual-mvc-completo.md +0 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extensión de Administración para JERK Framework
|
|
3
|
+
* Implementación del componente admin/AdminExtension.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const net = require('net');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
class AdminExtension {
|
|
11
|
+
/**
|
|
12
|
+
* Constructor de la extensión de administración
|
|
13
|
+
* @param {Object} options - Opciones de configuración
|
|
14
|
+
* @param {number} options.port - Puerto para el servidor de administración
|
|
15
|
+
* @param {string} options.host - Host para el servidor de administración
|
|
16
|
+
*/
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.port = options.port || 9999;
|
|
19
|
+
this.host = options.host || '127.0.0.1'; // Solo localhost
|
|
20
|
+
this.server = null;
|
|
21
|
+
this.clients = new Set();
|
|
22
|
+
this.frameworkVersion = this.getFrameworkVersion();
|
|
23
|
+
this.activeRoutes = new Map(); // Para rastrear rutas activas
|
|
24
|
+
this.registeredRoutes = []; // Para almacenar rutas registradas
|
|
25
|
+
this.modules = new Map(); // Para almacenar módulos de administración
|
|
26
|
+
this.hooks = null; // Referencia al sistema de hooks
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Obtiene la versión del framework desde package.json
|
|
31
|
+
* @returns {string} - Versión del framework
|
|
32
|
+
*/
|
|
33
|
+
getFrameworkVersion() {
|
|
34
|
+
try {
|
|
35
|
+
const packagePath = path.join(__dirname, '../../package.json');
|
|
36
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
37
|
+
return packageJson.version || 'unknown';
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('Error leyendo la versión del framework:', error.message);
|
|
40
|
+
return 'unknown';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Inicializa la extensión y el servidor de administración
|
|
46
|
+
* @param {Object} frameworkInstance - Instancia del framework JERK
|
|
47
|
+
*/
|
|
48
|
+
initialize(frameworkInstance) {
|
|
49
|
+
this.frameworkInstance = frameworkInstance;
|
|
50
|
+
|
|
51
|
+
// Obtener referencia al sistema de hooks
|
|
52
|
+
if (frameworkInstance && frameworkInstance.hooks) {
|
|
53
|
+
this.hooks = frameworkInstance.hooks;
|
|
54
|
+
} else {
|
|
55
|
+
// Si no se proporciona, crear uno nuevo
|
|
56
|
+
const { hooks } = require('../../index.js');
|
|
57
|
+
this.hooks = hooks;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Registrar hooks para rastrear rutas
|
|
61
|
+
this.registerHooks();
|
|
62
|
+
|
|
63
|
+
// Registrar módulos
|
|
64
|
+
this.registerModules();
|
|
65
|
+
|
|
66
|
+
// Cargar módulos personalizados
|
|
67
|
+
this.loadCustomModules();
|
|
68
|
+
|
|
69
|
+
// Cargar rutas existentes si el servidor ya tiene rutas registradas
|
|
70
|
+
this.loadExistingRoutes();
|
|
71
|
+
|
|
72
|
+
// Iniciar servidor de administración
|
|
73
|
+
this.startAdminServer();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Carga módulos personalizados
|
|
78
|
+
*/
|
|
79
|
+
loadCustomModules() {
|
|
80
|
+
try {
|
|
81
|
+
const ModuleLoader = require('./ModuleLoader');
|
|
82
|
+
const moduleLoader = new ModuleLoader(this);
|
|
83
|
+
|
|
84
|
+
// Cargar módulos desde el directorio de módulos
|
|
85
|
+
moduleLoader.loadModulesFromDirectory('./modules');
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('Error cargando módulos personalizados:', error.message);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Carga las rutas existentes en el servidor
|
|
93
|
+
*/
|
|
94
|
+
loadExistingRoutes() {
|
|
95
|
+
if (this.frameworkInstance && this.frameworkInstance.routes) {
|
|
96
|
+
// Copiar las rutas existentes al registro de rutas registradas
|
|
97
|
+
for (const route of this.frameworkInstance.routes) {
|
|
98
|
+
this.registeredRoutes.push({
|
|
99
|
+
method: route.method,
|
|
100
|
+
path: route.path,
|
|
101
|
+
handler: route.handler,
|
|
102
|
+
isStatic: route.isStatic
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Registra los hooks necesarios para rastrear rutas
|
|
110
|
+
*/
|
|
111
|
+
registerHooks() {
|
|
112
|
+
if (this.hooks) {
|
|
113
|
+
// Hook para rastrear rutas registradas
|
|
114
|
+
this.hooks.addAction('route_registered', (route) => {
|
|
115
|
+
this.registeredRoutes.push(route);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// Hook para rastrear rutas activas
|
|
119
|
+
this.hooks.addAction('request_received', (req, res) => {
|
|
120
|
+
const routeInfo = {
|
|
121
|
+
method: req.method,
|
|
122
|
+
url: req.url,
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
remoteAddress: req.connection.remoteAddress
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Usar la URL como clave y almacenar la última solicitud
|
|
128
|
+
this.activeRoutes.set(req.url, routeInfo);
|
|
129
|
+
|
|
130
|
+
// Disparar hook específico para módulos de administración
|
|
131
|
+
this.hooks.doAction('admin_route_active', routeInfo);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Hook para cuando se cierra el servidor
|
|
135
|
+
this.hooks.addAction('server_stopped', () => {
|
|
136
|
+
this.close();
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Registra los módulos de administración
|
|
143
|
+
*/
|
|
144
|
+
registerModules() {
|
|
145
|
+
// Módulo de rutas - el primer módulo
|
|
146
|
+
this.modules.set('routes', {
|
|
147
|
+
name: 'Routes Module',
|
|
148
|
+
description: 'Módulo para ver rutas registradas y activas',
|
|
149
|
+
commands: ['routes', 'active'],
|
|
150
|
+
handler: this.handleRoutesCommand.bind(this)
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Módulo de sistema - para comandos generales
|
|
154
|
+
this.modules.set('system', {
|
|
155
|
+
name: 'System Module',
|
|
156
|
+
description: 'Módulo para información del sistema',
|
|
157
|
+
commands: ['version', 'status', 'help'],
|
|
158
|
+
handler: this.handleSystemCommand.bind(this)
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Cargar módulos personalizados
|
|
162
|
+
this.loadCustomModules();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Carga módulos personalizados desde el directorio de módulos
|
|
167
|
+
*/
|
|
168
|
+
loadCustomModules() {
|
|
169
|
+
const fs = require('fs');
|
|
170
|
+
const path = require('path');
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const modulesDir = path.join(__dirname, 'modules');
|
|
174
|
+
|
|
175
|
+
if (fs.existsSync(modulesDir)) {
|
|
176
|
+
const files = fs.readdirSync(modulesDir);
|
|
177
|
+
|
|
178
|
+
for (const file of files) {
|
|
179
|
+
if (file.endsWith('.js') && file !== 'index.js') {
|
|
180
|
+
try {
|
|
181
|
+
const moduleName = file.replace('.js', '');
|
|
182
|
+
const ModuleClass = require(path.join(modulesDir, file));
|
|
183
|
+
|
|
184
|
+
if (typeof ModuleClass === 'function') {
|
|
185
|
+
const moduleInstance = new ModuleClass(this);
|
|
186
|
+
|
|
187
|
+
this.modules.set(moduleName.toLowerCase(), {
|
|
188
|
+
name: moduleInstance.name,
|
|
189
|
+
description: moduleInstance.description,
|
|
190
|
+
commands: moduleInstance.commands,
|
|
191
|
+
handler: (command, socket) => moduleInstance.handleCommand(command, socket)
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
console.log(`Módulo '${moduleName}' cargado exitosamente.`);
|
|
195
|
+
}
|
|
196
|
+
} catch (moduleError) {
|
|
197
|
+
console.error(`Error cargando módulo ${file}:`, moduleError.message);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error('Error general al cargar módulos personalizados:', error.message);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Manejador para el módulo de rutas
|
|
209
|
+
*/
|
|
210
|
+
handleRoutesCommand(command, socket) {
|
|
211
|
+
switch (command) {
|
|
212
|
+
case 'routes':
|
|
213
|
+
this.sendRegisteredRoutes(socket);
|
|
214
|
+
break;
|
|
215
|
+
case 'active':
|
|
216
|
+
this.sendActiveRoutes(socket);
|
|
217
|
+
break;
|
|
218
|
+
default:
|
|
219
|
+
socket.write(`Comando desconocido para el módulo de rutas: ${command}\n`);
|
|
220
|
+
socket.write(`Comandos disponibles: routes, active\n\n`);
|
|
221
|
+
socket.write(`> `);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Manejador para el módulo de sistema
|
|
227
|
+
*/
|
|
228
|
+
handleSystemCommand(command, socket) {
|
|
229
|
+
switch (command) {
|
|
230
|
+
case 'version':
|
|
231
|
+
socket.write(`\nVersión del framework: ${this.frameworkVersion}\n\n`);
|
|
232
|
+
socket.write(`> `);
|
|
233
|
+
break;
|
|
234
|
+
case 'status':
|
|
235
|
+
socket.write(`\nEstado del servidor:\n`);
|
|
236
|
+
socket.write(`- Puerto: ${this.port}\n`);
|
|
237
|
+
socket.write(`- Host: ${this.host}\n`);
|
|
238
|
+
socket.write(`- Clientes conectados: ${this.clients.size}\n`);
|
|
239
|
+
socket.write(`- Rutas registradas: ${this.registeredRoutes.length}\n`);
|
|
240
|
+
socket.write(`- Rutas activas: ${this.activeRoutes.size}\n\n`);
|
|
241
|
+
socket.write(`> `);
|
|
242
|
+
break;
|
|
243
|
+
case 'help':
|
|
244
|
+
this.sendHelp(socket);
|
|
245
|
+
break;
|
|
246
|
+
default:
|
|
247
|
+
socket.write(`Comando desconocido para el módulo de sistema: ${command}\n`);
|
|
248
|
+
socket.write(`Comandos disponibles: version, status, help\n\n`);
|
|
249
|
+
socket.write(`> `);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Inicia el servidor de administración
|
|
255
|
+
*/
|
|
256
|
+
startAdminServer() {
|
|
257
|
+
this.server = net.createServer((socket) => {
|
|
258
|
+
this.clients.add(socket);
|
|
259
|
+
|
|
260
|
+
// Enviar mensaje de bienvenida
|
|
261
|
+
socket.write(`Bienvenido al Servidor de Administración de JERK Framework\n`);
|
|
262
|
+
socket.write(`Versión: ${this.frameworkVersion}\n`);
|
|
263
|
+
socket.write(`Puerto: ${this.port}\n`);
|
|
264
|
+
socket.write(`Fecha: ${new Date().toISOString()}\n\n`);
|
|
265
|
+
|
|
266
|
+
socket.write(`Módulos disponibles:\n`);
|
|
267
|
+
for (const [name, module] of this.modules) {
|
|
268
|
+
socket.write(` ${name}: ${module.description}\n`);
|
|
269
|
+
}
|
|
270
|
+
socket.write(`\n`);
|
|
271
|
+
|
|
272
|
+
socket.write(`Comandos disponibles:\n`);
|
|
273
|
+
for (const [name, module] of this.modules) {
|
|
274
|
+
socket.write(` ${module.commands.join(', ')} - ${module.description}\n`);
|
|
275
|
+
}
|
|
276
|
+
socket.write(` help - Mostrar esta ayuda\n`);
|
|
277
|
+
socket.write(` quit - Cerrar conexión\n\n`);
|
|
278
|
+
|
|
279
|
+
socket.write(`> `);
|
|
280
|
+
|
|
281
|
+
socket.on('data', (data) => {
|
|
282
|
+
const input = data.toString();
|
|
283
|
+
// Dividir la entrada en líneas y procesar cada una
|
|
284
|
+
const lines = input.split('\n').filter(line => line.trim() !== '');
|
|
285
|
+
|
|
286
|
+
for (const line of lines) {
|
|
287
|
+
const command = line.trim().toLowerCase();
|
|
288
|
+
console.log(`DEBUG: Comando recibido: "${command}"`); // Mensaje de depuración
|
|
289
|
+
|
|
290
|
+
// Verificar si es un comando de sistema
|
|
291
|
+
if (['help', 'quit', 'exit'].includes(command)) {
|
|
292
|
+
console.log(`DEBUG: Comando de sistema encontrado: ${command}`); // Mensaje de depuración
|
|
293
|
+
switch (command) {
|
|
294
|
+
case 'help':
|
|
295
|
+
this.sendHelp(socket);
|
|
296
|
+
break;
|
|
297
|
+
case 'quit':
|
|
298
|
+
case 'exit':
|
|
299
|
+
socket.write('Cerrando conexión...\n');
|
|
300
|
+
socket.end();
|
|
301
|
+
return;
|
|
302
|
+
default:
|
|
303
|
+
socket.write(`> `);
|
|
304
|
+
}
|
|
305
|
+
continue; // Continuar con la siguiente línea
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Buscar el módulo que maneje este comando
|
|
309
|
+
let handled = false;
|
|
310
|
+
console.log(`DEBUG: Buscando módulo para el comando "${command}"`); // Mensaje de depuración
|
|
311
|
+
console.log(`DEBUG: Módulos disponibles:`, Array.from(this.modules.keys())); // Mensaje de depuración
|
|
312
|
+
|
|
313
|
+
for (const [moduleName, module] of this.modules) {
|
|
314
|
+
console.log(`DEBUG: Revisando módulo "${moduleName}", comandos:`, module.commands); // Mensaje de depuración
|
|
315
|
+
if (module.commands.includes(command)) {
|
|
316
|
+
console.log(`DEBUG: Módulo encontrado para el comando "${command}", llamando handler`); // Mensaje de depuración
|
|
317
|
+
module.handler(command, socket);
|
|
318
|
+
handled = true;
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (!handled) {
|
|
324
|
+
console.log(`DEBUG: Comando no encontrado: "${command}"`); // Mensaje de depuración
|
|
325
|
+
socket.write(`Comando desconocido: ${command}\n`);
|
|
326
|
+
socket.write(`Escribe 'help' para ver los comandos disponibles.\n\n`);
|
|
327
|
+
socket.write(`> `);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
socket.on('close', () => {
|
|
333
|
+
this.clients.delete(socket);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
socket.on('error', (err) => {
|
|
337
|
+
console.error('Error en el socket de administración:', err);
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
this.server.listen(this.port, this.host, () => {
|
|
342
|
+
console.log(`Servidor de administración JERK iniciado en ${this.host}:${this.port}`);
|
|
343
|
+
console.log(`Versión del framework: ${this.frameworkVersion}`);
|
|
344
|
+
|
|
345
|
+
// Disparar hook cuando se inicia el servidor de administración
|
|
346
|
+
if (this.hooks) {
|
|
347
|
+
this.hooks.doAction('admin_server_started', this.port, this.host);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
this.server.on('error', (err) => {
|
|
352
|
+
console.error('Error en el servidor de administración:', err);
|
|
353
|
+
|
|
354
|
+
// Disparar hook cuando hay un error en el servidor de administración
|
|
355
|
+
if (this.hooks) {
|
|
356
|
+
this.hooks.doAction('admin_server_error', err);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Envía la lista de rutas registradas al cliente
|
|
363
|
+
* @param {Object} socket - Socket del cliente
|
|
364
|
+
*/
|
|
365
|
+
sendRegisteredRoutes(socket) {
|
|
366
|
+
socket.write('\n=== Rutas Registradas ===\n');
|
|
367
|
+
|
|
368
|
+
if (this.registeredRoutes.length === 0) {
|
|
369
|
+
socket.write('No hay rutas registradas.\n');
|
|
370
|
+
} else {
|
|
371
|
+
this.registeredRoutes.forEach((route, index) => {
|
|
372
|
+
socket.write(`${index + 1}. ${route.method} ${route.path}\n`);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
socket.write('\n> ');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Envía la lista de rutas activas al cliente
|
|
381
|
+
* @param {Object} socket - Socket del cliente
|
|
382
|
+
*/
|
|
383
|
+
sendActiveRoutes(socket) {
|
|
384
|
+
socket.write('\n=== Rutas Activas (Últimas Solicitudes) ===\n');
|
|
385
|
+
|
|
386
|
+
if (this.activeRoutes.size === 0) {
|
|
387
|
+
socket.write('No hay rutas activas registradas.\n');
|
|
388
|
+
} else {
|
|
389
|
+
for (const [url, info] of this.activeRoutes) {
|
|
390
|
+
socket.write(`${info.method} ${url} - ${info.timestamp} (${info.remoteAddress})\n`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
socket.write('\n> ');
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Envía la ayuda al cliente
|
|
399
|
+
* @param {Object} socket - Socket del cliente
|
|
400
|
+
*/
|
|
401
|
+
sendHelp(socket) {
|
|
402
|
+
socket.write('\n=== Ayuda del Servidor de Administración ===\n');
|
|
403
|
+
socket.write(`Módulos disponibles:\n`);
|
|
404
|
+
for (const [name, module] of this.modules) {
|
|
405
|
+
socket.write(` ${name}: ${module.description}\n`);
|
|
406
|
+
socket.write(` Comandos: ${module.commands.join(', ')}\n`);
|
|
407
|
+
}
|
|
408
|
+
socket.write(`\nComandos generales:\n`);
|
|
409
|
+
socket.write(` help - Mostrar esta ayuda\n`);
|
|
410
|
+
socket.write(` quit - Cerrar conexión\n\n`);
|
|
411
|
+
socket.write(`> `);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Cierra el servidor de administración
|
|
416
|
+
*/
|
|
417
|
+
close() {
|
|
418
|
+
if (this.server) {
|
|
419
|
+
// Cerrar todas las conexiones de clientes
|
|
420
|
+
for (const client of this.clients) {
|
|
421
|
+
client.end();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
this.server.close(() => {
|
|
425
|
+
console.log('Servidor de administración cerrado');
|
|
426
|
+
|
|
427
|
+
// Disparar hook cuando se cierra el servidor de administración
|
|
428
|
+
if (this.hooks) {
|
|
429
|
+
this.hooks.doAction('admin_server_closed');
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
module.exports = AdminExtension;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sistema de Carga de Módulos Personalizados para la Extensión de Administración
|
|
3
|
+
* Permite cargar módulos externos como submódulos de la extensión
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class ModuleLoader {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor del cargador de módulos
|
|
12
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
13
|
+
*/
|
|
14
|
+
constructor(adminExtension) {
|
|
15
|
+
this.adminExtension = adminExtension;
|
|
16
|
+
this.modules = new Map();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Carga un módulo personalizado
|
|
21
|
+
* @param {string} moduleName - Nombre del módulo
|
|
22
|
+
* @param {Object} moduleClass - Clase del módulo
|
|
23
|
+
*/
|
|
24
|
+
loadModule(moduleName, moduleClass) {
|
|
25
|
+
const moduleInstance = new moduleClass(this.adminExtension);
|
|
26
|
+
this.modules.set(moduleName, moduleInstance);
|
|
27
|
+
|
|
28
|
+
// Registrar el módulo en la extensión de administración
|
|
29
|
+
this.adminExtension.modules.set(moduleName, {
|
|
30
|
+
name: moduleInstance.name,
|
|
31
|
+
description: moduleInstance.description,
|
|
32
|
+
commands: moduleInstance.commands,
|
|
33
|
+
handler: moduleInstance.handleCommand.bind(moduleInstance)
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
console.log(`Módulo '${moduleName}' cargado exitosamente.`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Carga módulos desde un directorio
|
|
41
|
+
* @param {string} directoryPath - Ruta del directorio de módulos
|
|
42
|
+
*/
|
|
43
|
+
loadModulesFromDirectory(directoryPath) {
|
|
44
|
+
const modulesDir = path.resolve(__dirname, directoryPath);
|
|
45
|
+
|
|
46
|
+
if (!fs.existsSync(modulesDir)) {
|
|
47
|
+
console.log(`Directorio de módulos no encontrado: ${modulesDir}`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const files = fs.readdirSync(modulesDir);
|
|
52
|
+
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
if (file.endsWith('.js') && file !== 'index.js') {
|
|
55
|
+
const moduleName = file.replace('.js', '');
|
|
56
|
+
const modulePath = path.join(modulesDir, file);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const ModuleClass = require(modulePath);
|
|
60
|
+
this.loadModule(moduleName.toLowerCase(), ModuleClass);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`Error cargando módulo ${file}:`, error.message);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Obtiene todos los módulos cargados
|
|
70
|
+
* @returns {Map} - Mapa de módulos cargados
|
|
71
|
+
*/
|
|
72
|
+
getLoadedModules() {
|
|
73
|
+
return this.modules;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = ModuleLoader;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuración de la extensión de administración para JERK Framework
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
adminExtension: {
|
|
7
|
+
enabled: true,
|
|
8
|
+
port: 9999,
|
|
9
|
+
host: '127.0.0.1', // Solo localhost
|
|
10
|
+
modules: {
|
|
11
|
+
routes: {
|
|
12
|
+
enabled: true,
|
|
13
|
+
options: {}
|
|
14
|
+
},
|
|
15
|
+
system: {
|
|
16
|
+
enabled: true,
|
|
17
|
+
options: {}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Caché para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Submódulo personalizado para mostrar y gestionar el sistema de caché
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class CacheModule {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del módulo de caché
|
|
9
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
10
|
+
*/
|
|
11
|
+
constructor(adminExtension) {
|
|
12
|
+
this.adminExtension = adminExtension;
|
|
13
|
+
this.name = 'Cache Module';
|
|
14
|
+
this.description = 'Módulo para administrar y monitorear el sistema de caché';
|
|
15
|
+
this.commands = ['cache', 'cache-stats', 'cache-clear', 'cache-info'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Manejador para los comandos del módulo de caché
|
|
20
|
+
* @param {string} command - Comando a ejecutar
|
|
21
|
+
* @param {Object} socket - Socket de la conexión
|
|
22
|
+
*/
|
|
23
|
+
handleCommand(command, socket) {
|
|
24
|
+
switch (command) {
|
|
25
|
+
case 'cache':
|
|
26
|
+
case 'cache-info':
|
|
27
|
+
this.showCacheInfo(socket);
|
|
28
|
+
break;
|
|
29
|
+
case 'cache-stats':
|
|
30
|
+
this.showCacheStats(socket);
|
|
31
|
+
break;
|
|
32
|
+
case 'cache-clear':
|
|
33
|
+
this.clearCache(socket);
|
|
34
|
+
break;
|
|
35
|
+
default:
|
|
36
|
+
socket.write(`Comando desconocido para el módulo de caché: ${command}\n`);
|
|
37
|
+
socket.write(`Comandos disponibles: cache, cache-info, cache-stats, cache-clear\n\n`);
|
|
38
|
+
socket.write(`> `);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Muestra información general del sistema de caché
|
|
44
|
+
* @param {Object} socket - Socket de la conexión
|
|
45
|
+
*/
|
|
46
|
+
showCacheInfo(socket) {
|
|
47
|
+
const routeMatcher = this.getRouteMatcher();
|
|
48
|
+
const viewEngine = this.getViewEngine();
|
|
49
|
+
|
|
50
|
+
const routeCacheSize = routeMatcher ? routeMatcher.routeRegexCache.size : 0;
|
|
51
|
+
const viewCacheSize = viewEngine ? (viewEngine.viewCache ? viewEngine.viewCache.size : 0) : 0;
|
|
52
|
+
|
|
53
|
+
socket.write('\n=== Información del Sistema de Caché ===\n');
|
|
54
|
+
socket.write(`Caché de Expresiones Regulares: ${routeCacheSize} entradas\n`);
|
|
55
|
+
socket.write(`Caché de Vistas: ${viewCacheSize} entradas\n`);
|
|
56
|
+
socket.write(`\n> `);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Muestra estadísticas detalladas del sistema de caché
|
|
61
|
+
* @param {Object} socket - Socket de la conexión
|
|
62
|
+
*/
|
|
63
|
+
showCacheStats(socket) {
|
|
64
|
+
const routeMatcher = this.getRouteMatcher();
|
|
65
|
+
const viewEngine = this.getViewEngine();
|
|
66
|
+
|
|
67
|
+
const routeCacheSize = routeMatcher ? routeMatcher.routeRegexCache.size : 0;
|
|
68
|
+
const viewCacheSize = viewEngine ? (viewEngine.viewCache ? viewEngine.viewCache.size : 0) : 0;
|
|
69
|
+
|
|
70
|
+
socket.write('\n=== Estadísticas del Sistema de Caché ===\n');
|
|
71
|
+
socket.write(`Tamaño del caché de rutas: ${routeCacheSize}\n`);
|
|
72
|
+
socket.write(`Tamaño del caché de vistas: ${viewCacheSize}\n`);
|
|
73
|
+
|
|
74
|
+
// Mostrar algunos elementos del caché si existen
|
|
75
|
+
if (routeMatcher && routeMatcher.routeRegexCache.size > 0) {
|
|
76
|
+
socket.write('\nEntradas de caché de rutas (primeras 5):\n');
|
|
77
|
+
let count = 0;
|
|
78
|
+
for (const [path, regex] of routeMatcher.routeRegexCache) {
|
|
79
|
+
if (count >= 5) break;
|
|
80
|
+
socket.write(` ${path}: ${regex}\n`);
|
|
81
|
+
count++;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (viewEngine && viewEngine.viewCache && viewEngine.viewCache.size > 0) {
|
|
86
|
+
socket.write('\nEntradas de caché de vistas (primeras 5):\n');
|
|
87
|
+
let count = 0;
|
|
88
|
+
for (const [path, content] of viewEngine.viewCache) {
|
|
89
|
+
if (count >= 5) break;
|
|
90
|
+
socket.write(` ${path}: ${content.length} chars\n`);
|
|
91
|
+
count++;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
socket.write(`\n> `);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Limpia todos los sistemas de caché
|
|
100
|
+
* @param {Object} socket - Socket de la conexión
|
|
101
|
+
*/
|
|
102
|
+
clearCache(socket) {
|
|
103
|
+
const routeMatcher = this.getRouteMatcher();
|
|
104
|
+
const viewEngine = this.getViewEngine();
|
|
105
|
+
|
|
106
|
+
let clearedSystems = [];
|
|
107
|
+
|
|
108
|
+
if (routeMatcher) {
|
|
109
|
+
routeMatcher.clearCache(); // Usar el nuevo método que dispara hooks
|
|
110
|
+
clearedSystems.push('caché de rutas');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (viewEngine && viewEngine.viewCache) {
|
|
114
|
+
viewEngine.clearCache(); // Usar el nuevo método que dispara hooks
|
|
115
|
+
clearedSystems.push('caché de vistas');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
socket.write(`\nSistemas de caché limpiados: ${clearedSystems.join(', ')}\n`);
|
|
119
|
+
socket.write(`\n> `);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Obtiene la instancia de RouteMatcher si está disponible
|
|
124
|
+
* @returns {Object|null} - Instancia de RouteMatcher o null
|
|
125
|
+
*/
|
|
126
|
+
getRouteMatcher() {
|
|
127
|
+
if (this.adminExtension.frameworkInstance && this.adminExtension.frameworkInstance.routeMatcher) {
|
|
128
|
+
return this.adminExtension.frameworkInstance.routeMatcher;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Obtiene la instancia de ViewEngine si está disponible
|
|
135
|
+
* @returns {Object|null} - Instancia de ViewEngine o null
|
|
136
|
+
*/
|
|
137
|
+
getViewEngine() {
|
|
138
|
+
if (this.adminExtension.frameworkInstance && this.adminExtension.frameworkInstance.viewEngine) {
|
|
139
|
+
return this.adminExtension.frameworkInstance.viewEngine;
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
module.exports = CacheModule;
|