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,98 @@
|
|
|
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
|
+
## Instalación
|
|
67
|
+
|
|
68
|
+
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.
|
|
69
|
+
|
|
70
|
+
## Uso
|
|
71
|
+
|
|
72
|
+
1. Inicialice la extensión de administración en su servidor:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
const server = new APIServer({ port: 3000 });
|
|
76
|
+
server.initializeAdminExtension({
|
|
77
|
+
port: 9999,
|
|
78
|
+
host: '127.0.0.1'
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
2. Conéctese al servidor de administración:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
telnet localhost 9999
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. Use cualquiera de los comandos disponibles:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
stats
|
|
92
|
+
requests
|
|
93
|
+
endpoints
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Contribución
|
|
97
|
+
|
|
98
|
+
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.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Estadísticas para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para mostrar estadísticas del servidor
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class StatsModule {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del módulo de estadísticas
|
|
9
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
10
|
+
*/
|
|
11
|
+
constructor(adminExtension) {
|
|
12
|
+
this.adminExtension = adminExtension;
|
|
13
|
+
this.name = 'Statistics Module';
|
|
14
|
+
this.description = 'Módulo para mostrar estadísticas del servidor';
|
|
15
|
+
this.commands = ['stats', 'statistics', 'requests', 'endpoints'];
|
|
16
|
+
|
|
17
|
+
// Cargar el objeto global de estadísticas
|
|
18
|
+
this.globalStats = require('../../utils/globalStats').globalStats;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Manejador para los comandos del módulo de estadísticas
|
|
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 'stats':
|
|
29
|
+
case 'statistics':
|
|
30
|
+
this.showGeneralStats(socket);
|
|
31
|
+
break;
|
|
32
|
+
case 'requests':
|
|
33
|
+
this.showRequestStats(socket);
|
|
34
|
+
break;
|
|
35
|
+
case 'endpoints':
|
|
36
|
+
this.showEndpointStats(socket);
|
|
37
|
+
break;
|
|
38
|
+
default:
|
|
39
|
+
socket.write(`Comando desconocido para el módulo de estadísticas: ${command}\n`);
|
|
40
|
+
socket.write(`Comandos disponibles: stats, statistics, requests, endpoints\n\n`);
|
|
41
|
+
socket.write(`> `);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Muestra estadísticas generales
|
|
47
|
+
* @param {Object} socket - Socket de la conexión
|
|
48
|
+
*/
|
|
49
|
+
showGeneralStats(socket) {
|
|
50
|
+
const formattedRequestBytes = this.formatBytes(this.globalStats.requestBytes);
|
|
51
|
+
const formattedResponseBytes = this.formatBytes(this.globalStats.responseBytes);
|
|
52
|
+
|
|
53
|
+
socket.write('\n=== Estadísticas Generales ===\n');
|
|
54
|
+
socket.write(`Solicitudes procesadas: ${this.globalStats.requestsProcessed}\n`);
|
|
55
|
+
socket.write(`Solicitudes procesadas (KB): ${formattedRequestBytes}\n`);
|
|
56
|
+
socket.write(`Respuestas enviadas: ${this.globalStats.responsesSent}\n`);
|
|
57
|
+
socket.write(`Respuestas enviadas (KB): ${formattedResponseBytes}\n`);
|
|
58
|
+
socket.write(`Rutas registradas: ${this.adminExtension.registeredRoutes.length}\n`);
|
|
59
|
+
socket.write(`Rutas activas: ${this.adminExtension.activeRoutes.size}\n\n`);
|
|
60
|
+
socket.write(`> `);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Muestra estadísticas de solicitudes
|
|
65
|
+
* @param {Object} socket - Socket de la conexión
|
|
66
|
+
*/
|
|
67
|
+
showRequestStats(socket) {
|
|
68
|
+
socket.write('\n=== Estadísticas de Solicitudes ===\n');
|
|
69
|
+
socket.write(`Total de solicitudes procesadas: ${this.globalStats.requestsProcessed}\n`);
|
|
70
|
+
socket.write(`Total de bytes recibidos: ${this.formatBytes(this.globalStats.requestBytes)}\n`);
|
|
71
|
+
|
|
72
|
+
// Mostrar accesos a rutas
|
|
73
|
+
if (this.globalStats.routeAccesses.size > 0) {
|
|
74
|
+
socket.write('\nAccesos a rutas (Input/Output):\n');
|
|
75
|
+
for (const [route, count] of this.globalStats.routeAccesses) {
|
|
76
|
+
socket.write(` ${route}: ${count} accesos\n`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
socket.write('\n> ');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Muestra estadísticas de endpoints
|
|
85
|
+
* @param {Object} socket - Socket de la conexión
|
|
86
|
+
*/
|
|
87
|
+
showEndpointStats(socket) {
|
|
88
|
+
socket.write('\n=== Estadísticas de Endpoints y Rutas ===\n');
|
|
89
|
+
|
|
90
|
+
// Mostrar endpoints más accedidos
|
|
91
|
+
if (this.globalStats.endpointHits.size > 0) {
|
|
92
|
+
socket.write('Endpoints más accedidos:\n');
|
|
93
|
+
|
|
94
|
+
// Convertir el mapa a array y ordenar por número de hits
|
|
95
|
+
const sortedEndpoints = Array.from(this.globalStats.endpointHits.entries())
|
|
96
|
+
.sort((a, b) => b[1] - a[1])
|
|
97
|
+
.slice(0, 10); // Mostrar top 10
|
|
98
|
+
|
|
99
|
+
for (const [endpoint, hits] of sortedEndpoints) {
|
|
100
|
+
socket.write(` ${endpoint}: ${hits} hits\n`);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
socket.write('No hay datos de endpoints accedidos.\n');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Mostrar rutas más accedidas
|
|
107
|
+
if (this.globalStats.routeAccesses.size > 0) {
|
|
108
|
+
socket.write('\nRutas más accedidas:\n');
|
|
109
|
+
|
|
110
|
+
// Convertir el mapa a array y ordenar por número de accesos
|
|
111
|
+
const sortedRoutes = Array.from(this.globalStats.routeAccesses.entries())
|
|
112
|
+
.sort((a, b) => b[1] - a[1])
|
|
113
|
+
.slice(0, 10); // Mostrar top 10
|
|
114
|
+
|
|
115
|
+
for (const [route, accesses] of sortedRoutes) {
|
|
116
|
+
socket.write(` ${route}: ${accesses} accesos\n`);
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
socket.write('\nNo hay datos de rutas accedidas.\n');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
socket.write('\n> ');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Formatea bytes a una unidad legible
|
|
127
|
+
* @param {number} bytes - Cantidad en bytes
|
|
128
|
+
* @returns {string} - Cantidad formateada con unidad
|
|
129
|
+
*/
|
|
130
|
+
formatBytes(bytes) {
|
|
131
|
+
// Manejar valores nulos o indefinidos
|
|
132
|
+
if (bytes == null || isNaN(bytes) || bytes === 0) return '0 Bytes';
|
|
133
|
+
const k = 1024;
|
|
134
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
135
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
136
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = StatsModule;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Sistema para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para mostrar información del sistema
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class SystemModule {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del módulo de sistema
|
|
9
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
10
|
+
*/
|
|
11
|
+
constructor(adminExtension) {
|
|
12
|
+
this.adminExtension = adminExtension;
|
|
13
|
+
this.name = 'System Info Module';
|
|
14
|
+
this.description = 'Módulo para mostrar información del sistema';
|
|
15
|
+
this.commands = ['sysinfo', 'system', 'resources'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Manejador para los comandos del módulo de sistema
|
|
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 'sysinfo':
|
|
26
|
+
case 'system':
|
|
27
|
+
case 'resources':
|
|
28
|
+
this.showSystemInfo(socket);
|
|
29
|
+
break;
|
|
30
|
+
default:
|
|
31
|
+
socket.write(`Comando desconocido para el módulo de sistema: ${command}\n`);
|
|
32
|
+
socket.write(`Comandos disponibles: sysinfo, system, resources\n\n`);
|
|
33
|
+
socket.write(`> `);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Muestra información del sistema en formato de tabla con color verde
|
|
39
|
+
* @param {Object} socket - Socket de la conexión
|
|
40
|
+
*/
|
|
41
|
+
showSystemInfo(socket) {
|
|
42
|
+
const os = require('os');
|
|
43
|
+
const memUsage = process.memoryUsage();
|
|
44
|
+
const cpuInfo = os.cpus();
|
|
45
|
+
const totalMem = os.totalmem();
|
|
46
|
+
const freeMem = os.freemem();
|
|
47
|
+
const usedMem = totalMem - freeMem;
|
|
48
|
+
const uptime = process.uptime();
|
|
49
|
+
|
|
50
|
+
// Obtener información del proceso
|
|
51
|
+
const pid = process.pid;
|
|
52
|
+
const ppid = process.ppid;
|
|
53
|
+
const execPath = process.execPath;
|
|
54
|
+
const version = process.version;
|
|
55
|
+
|
|
56
|
+
// Calcular uso de CPU (aproximado)
|
|
57
|
+
let totalIdle = 0, totalTick = 0;
|
|
58
|
+
for (const cpu of cpuInfo) {
|
|
59
|
+
for (const type in cpu.times) {
|
|
60
|
+
totalTick += cpu.times[type];
|
|
61
|
+
}
|
|
62
|
+
totalIdle += cpu.times.idle;
|
|
63
|
+
}
|
|
64
|
+
const avgTick = totalTick / cpuInfo.length;
|
|
65
|
+
const avgIdle = totalIdle / cpuInfo.length;
|
|
66
|
+
const cpuUsage = Math.round((1 - avgIdle / avgTick) * 10000) / 100;
|
|
67
|
+
|
|
68
|
+
// Formatear la información en una tabla
|
|
69
|
+
const table = `
|
|
70
|
+
\x1b[32m
|
|
71
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
72
|
+
║ INFORMACIÓN DEL SISTEMA ║
|
|
73
|
+
╠════════════════════════════════════════════════════════════════╣
|
|
74
|
+
║ Recursos del Sistema ║
|
|
75
|
+
╠────────────────────────────────────────────────────────────────╣
|
|
76
|
+
║ Memoria Total: ${this.padRight(this.formatBytes(totalMem), 15)} ║ Memoria Libre: ${this.padRight(this.formatBytes(freeMem), 15)} ║
|
|
77
|
+
║ Memoria Usada: ${this.padRight(this.formatBytes(usedMem), 15)} ║ Uso de CPU: ${this.padRight(cpuUsage + '%', 15)} ║
|
|
78
|
+
║ Procesos CPU: ${this.padRight(cpuInfo.length + '', 15)} ║ Uptime Proceso: ${this.padRight(this.formatUptime(uptime), 15)} ║
|
|
79
|
+
╠════════════════════════════════════════════════════════════════╣
|
|
80
|
+
║ Información del Proceso ║
|
|
81
|
+
╠────────────────────────────────────────────────────────────────╣
|
|
82
|
+
║ PID: ${this.padRight(pid + '', 15)} ║ PPID: ${this.padRight(ppid + '', 15)} ║
|
|
83
|
+
║ Versión Node: ${this.padRight(version, 15)} ║ Ruta Ejecutable: ${this.padRight(execPath.split('/').pop().substring(0, 15), 15)} ║
|
|
84
|
+
╠════════════════════════════════════════════════════════════════╣
|
|
85
|
+
║ Uso de Memoria del Proceso ║
|
|
86
|
+
╠────────────────────────────────────────────────────────────────╣
|
|
87
|
+
║ RSS: ${this.padRight(this.formatBytes(memUsage.rss), 15)} ║ Heap Total: ${this.padRight(this.formatBytes(memUsage.heapTotal), 15)} ║
|
|
88
|
+
║ Heap Usado: ${this.padRight(this.formatBytes(memUsage.heapUsed), 15)} ║ External: ${this.padRight(this.formatBytes(memUsage.external), 15)} ║
|
|
89
|
+
╚════════════════════════════════════════════════════════════════╝\x1b[0m`;
|
|
90
|
+
|
|
91
|
+
socket.write(table + '\n\n');
|
|
92
|
+
socket.write(`> `);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Formatea bytes a una unidad legible
|
|
97
|
+
* @param {number} bytes - Cantidad en bytes
|
|
98
|
+
* @returns {string} - Cantidad formateada con unidad
|
|
99
|
+
*/
|
|
100
|
+
formatBytes(bytes) {
|
|
101
|
+
if (bytes === 0) return '0 Bytes';
|
|
102
|
+
const k = 1024;
|
|
103
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
|
104
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
105
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Formatea el uptime en una cadena legible
|
|
110
|
+
* @param {number} seconds - Segundos de uptime
|
|
111
|
+
* @returns {string} - Uptime formateado
|
|
112
|
+
*/
|
|
113
|
+
formatUptime(seconds) {
|
|
114
|
+
const days = Math.floor(seconds / (3600 * 24));
|
|
115
|
+
const hours = Math.floor((seconds % (3600 * 24)) / 3600);
|
|
116
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
117
|
+
const secs = Math.floor(seconds % 60);
|
|
118
|
+
|
|
119
|
+
let result = '';
|
|
120
|
+
if (days > 0) result += `${days}d `;
|
|
121
|
+
if (hours > 0) result += `${hours}h `;
|
|
122
|
+
if (minutes > 0) result += `${minutes}m `;
|
|
123
|
+
result += `${secs}s`;
|
|
124
|
+
|
|
125
|
+
return result.trim();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Ajusta texto a la derecha con padding
|
|
130
|
+
* @param {string} str - Texto a ajustar
|
|
131
|
+
* @param {number} length - Longitud total
|
|
132
|
+
* @returns {string} - Texto ajustado
|
|
133
|
+
*/
|
|
134
|
+
padRight(str, length) {
|
|
135
|
+
str = str + '';
|
|
136
|
+
return str.length < length ? str + ' '.repeat(length - str.length) : str.substring(0, length);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = SystemModule;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Tiempo para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para mostrar hora y fecha
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class TimeModule {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del módulo de tiempo
|
|
9
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
10
|
+
*/
|
|
11
|
+
constructor(adminExtension) {
|
|
12
|
+
this.adminExtension = adminExtension;
|
|
13
|
+
this.name = 'Time Module';
|
|
14
|
+
this.description = 'Módulo para mostrar hora y fecha';
|
|
15
|
+
this.commands = ['time', 'date'];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Manejador para los comandos del módulo de tiempo
|
|
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 'time':
|
|
26
|
+
this.showTime(socket);
|
|
27
|
+
break;
|
|
28
|
+
case 'date':
|
|
29
|
+
this.showDate(socket);
|
|
30
|
+
break;
|
|
31
|
+
default:
|
|
32
|
+
socket.write(`Comando desconocido para el módulo de tiempo: ${command}\n`);
|
|
33
|
+
socket.write(`Comandos disponibles: time, date\n\n`);
|
|
34
|
+
socket.write(`> `);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Muestra la hora actual en color azul
|
|
40
|
+
* @param {Object} socket - Socket de la conexión
|
|
41
|
+
*/
|
|
42
|
+
showTime(socket) {
|
|
43
|
+
const currentTime = new Date().toLocaleTimeString('es-ES', {
|
|
44
|
+
hour: '2-digit',
|
|
45
|
+
minute: '2-digit',
|
|
46
|
+
second: '2-digit',
|
|
47
|
+
hour12: false
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Enviar con código de color azul ANSI
|
|
51
|
+
socket.write(`\n\x1b[34mHora actual: ${currentTime}\x1b[0m\n\n`);
|
|
52
|
+
socket.write(`> `);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Muestra la fecha actual en color azul
|
|
57
|
+
* @param {Object} socket - Socket de la conexión
|
|
58
|
+
*/
|
|
59
|
+
showDate(socket) {
|
|
60
|
+
const currentDate = new Date().toLocaleDateString('es-ES', {
|
|
61
|
+
weekday: 'long',
|
|
62
|
+
year: 'numeric',
|
|
63
|
+
month: 'long',
|
|
64
|
+
day: 'numeric'
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Enviar con código de color azul ANSI
|
|
68
|
+
socket.write(`\n\x1b[34mFecha actual: ${currentDate}\x1b[0m\n\n`);
|
|
69
|
+
socket.write(`> `);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Muestra la fecha y hora actual en color azul
|
|
74
|
+
* @param {Object} socket - Socket de la conexión
|
|
75
|
+
*/
|
|
76
|
+
showDateTime(socket) {
|
|
77
|
+
const now = new Date();
|
|
78
|
+
const dateTime = now.toLocaleString('es-ES', {
|
|
79
|
+
weekday: 'long',
|
|
80
|
+
year: 'numeric',
|
|
81
|
+
month: 'long',
|
|
82
|
+
day: 'numeric',
|
|
83
|
+
hour: '2-digit',
|
|
84
|
+
minute: '2-digit',
|
|
85
|
+
second: '2-digit',
|
|
86
|
+
hour12: false
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Enviar con código de color azul ANSI
|
|
90
|
+
socket.write(`\n\x1b[34mFecha y hora actual: ${dateTime}\x1b[0m\n\n`);
|
|
91
|
+
socket.write(`> `);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = TimeModule;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sistema de Hooks y Filters para el Manejo de Caché en JERK Framework
|
|
3
|
+
* Implementación del componente cache/cacheHooks.js
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class CacheHooks {
|
|
7
|
+
/**
|
|
8
|
+
* Constructor del sistema de hooks de caché
|
|
9
|
+
* @param {Object} hooksSystem - Instancia del sistema de hooks principal
|
|
10
|
+
*/
|
|
11
|
+
constructor(hooksSystem) {
|
|
12
|
+
this.hooks = hooksSystem;
|
|
13
|
+
this.initializeCacheHooks();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Inicializa los hooks relacionados con el sistema de caché
|
|
18
|
+
*/
|
|
19
|
+
initializeCacheHooks() {
|
|
20
|
+
// Hook para cuando se añade una entrada al caché de rutas
|
|
21
|
+
this.hooks.addAction('route_regex_cached', (path, regex) => {
|
|
22
|
+
console.log(`[CACHE] Expresión regular cacheada para ruta: ${path}`);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Hook para cuando se añade una vista al caché
|
|
26
|
+
this.hooks.addAction('view_cached', (viewPath, content) => {
|
|
27
|
+
console.log(`[CACHE] Vista cacheada: ${viewPath}`);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Hook para cuando se limpia el caché de rutas
|
|
31
|
+
this.hooks.addAction('route_cache_cleared', () => {
|
|
32
|
+
console.log('[CACHE] Caché de rutas limpiado');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Hook para cuando se limpia el caché de vistas
|
|
36
|
+
this.hooks.addAction('view_cache_cleared', () => {
|
|
37
|
+
console.log('[CACHE] Caché de vistas limpiado');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Filter para permitir modificar el contenido antes de ser cacheado
|
|
41
|
+
this.hooks.addFilter('before_view_cache', (content, viewPath) => {
|
|
42
|
+
// Permitir a otros módulos modificar el contenido antes de cachear
|
|
43
|
+
return content;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Filter para permitir modificar la decisión de si se debe cachear una vista
|
|
47
|
+
this.hooks.addFilter('should_cache_view', (shouldCache, viewPath, content) => {
|
|
48
|
+
// Por defecto, se cachea si está habilitado globalmente
|
|
49
|
+
return shouldCache;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Filter para permitir modificar la decisión de si se debe cachear una expresión regular
|
|
53
|
+
this.hooks.addFilter('should_cache_route_regex', (shouldCache, path, regex) => {
|
|
54
|
+
// Por defecto, se cachea si está habilitado globalmente
|
|
55
|
+
return shouldCache;
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Dispara el hook cuando se añade una entrada al caché de rutas
|
|
61
|
+
* @param {string} path - Ruta que se está cacheando
|
|
62
|
+
* @param {RegExp} regex - Expresión regular que se está cacheando
|
|
63
|
+
*/
|
|
64
|
+
triggerRouteRegexCached(path, regex) {
|
|
65
|
+
if (this.hooks) {
|
|
66
|
+
this.hooks.doAction('route_regex_cached', path, regex);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Dispara el hook cuando se añade una vista al caché
|
|
72
|
+
* @param {string} viewPath - Ruta de la vista que se está cacheando
|
|
73
|
+
* @param {string} content - Contenido de la vista que se está cacheando
|
|
74
|
+
*/
|
|
75
|
+
triggerViewCached(viewPath, content) {
|
|
76
|
+
if (this.hooks) {
|
|
77
|
+
this.hooks.doAction('view_cached', viewPath, content);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Dispara el hook cuando se limpia el caché de rutas
|
|
83
|
+
*/
|
|
84
|
+
triggerRouteCacheCleared() {
|
|
85
|
+
if (this.hooks) {
|
|
86
|
+
this.hooks.doAction('route_cache_cleared');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Dispara el hook cuando se limpia el caché de vistas
|
|
92
|
+
*/
|
|
93
|
+
triggerViewCacheCleared() {
|
|
94
|
+
if (this.hooks) {
|
|
95
|
+
this.hooks.doAction('view_cache_cleared');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Aplica el filter antes de cachear una vista
|
|
101
|
+
* @param {string} content - Contenido de la vista
|
|
102
|
+
* @param {string} viewPath - Ruta de la vista
|
|
103
|
+
* @returns {string} - Contenido procesado por los filters
|
|
104
|
+
*/
|
|
105
|
+
applyBeforeViewCacheFilter(content, viewPath) {
|
|
106
|
+
if (this.hooks) {
|
|
107
|
+
return this.hooks.applyFilters('before_view_cache', content, viewPath);
|
|
108
|
+
}
|
|
109
|
+
return content;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Aplica el filter para decidir si se debe cachear una vista
|
|
114
|
+
* @param {boolean} shouldCache - Valor por defecto
|
|
115
|
+
* @param {string} viewPath - Ruta de la vista
|
|
116
|
+
* @param {string} content - Contenido de la vista
|
|
117
|
+
* @returns {boolean} - Decisión final de si se debe cachear
|
|
118
|
+
*/
|
|
119
|
+
applyShouldCacheViewFilter(shouldCache, viewPath, content) {
|
|
120
|
+
if (this.hooks) {
|
|
121
|
+
return this.hooks.applyFilters('should_cache_view', shouldCache, viewPath, content);
|
|
122
|
+
}
|
|
123
|
+
return shouldCache;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Aplica el filter para decidir si se debe cachear una expresión regular
|
|
128
|
+
* @param {boolean} shouldCache - Valor por defecto
|
|
129
|
+
* @param {string} path - Ruta para la que se va a cachear la expresión regular
|
|
130
|
+
* @param {RegExp} regex - Expresión regular a cachear
|
|
131
|
+
* @returns {boolean} - Decisión final de si se debe cachear
|
|
132
|
+
*/
|
|
133
|
+
applyShouldCacheRouteRegexFilter(shouldCache, path, regex) {
|
|
134
|
+
if (this.hooks) {
|
|
135
|
+
return this.hooks.applyFilters('should_cache_route_regex', shouldCache, path, regex);
|
|
136
|
+
}
|
|
137
|
+
return shouldCache;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
module.exports = CacheHooks;
|