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,229 @@
|
|
|
1
|
+
# Manual del Módulo WAF (Web Application Firewall) para JERK Framework
|
|
2
|
+
|
|
3
|
+
## Tabla de Contenidos
|
|
4
|
+
1. [Introducción](#introducción)
|
|
5
|
+
2. [Características del WAF](#características-del-waf)
|
|
6
|
+
3. [Comandos Disponibles](#comandos-disponibles)
|
|
7
|
+
4. [Estadísticas del Servidor](#estadísticas-del-servidor)
|
|
8
|
+
5. [Gestión de Reglas X-Headers](#gestión-de-reglas-x-headers)
|
|
9
|
+
6. [Listas de IPs](#listas-de-ips)
|
|
10
|
+
7. [Persistencia de Reglas](#persistencia-de-reglas)
|
|
11
|
+
8. [Ejemplos de Uso](#ejemplos-de-uso)
|
|
12
|
+
|
|
13
|
+
## Introducción
|
|
14
|
+
|
|
15
|
+
El módulo WAF (Web Application Firewall) es una extensión de la extensión de administración de JERK Framework que permite monitorear, gestionar y proteger tu aplicación web. Proporciona estadísticas en tiempo real, gestión de reglas de seguridad y control de acceso basado en headers X-.
|
|
16
|
+
|
|
17
|
+
## Características del WAF
|
|
18
|
+
|
|
19
|
+
- **Estadísticas en tiempo real**: Conteo de solicitudes procesadas y respuestas enviadas con medición en kilobytes
|
|
20
|
+
- **Monitoreo de tráfico**: Registro de accesos a rutas y endpoints
|
|
21
|
+
- **Sistema de reglas X-Headers**: Bloqueo basado en headers como X-Forwarded-For, X-Real-IP, etc.
|
|
22
|
+
- **Listas de IPs**: Sistema de whitelist (nunca bloqueadas) y blacklist (siempre bloqueadas)
|
|
23
|
+
- **Persistencia**: Guardado y carga de reglas de seguridad
|
|
24
|
+
- **Interfaz interactiva**: Sistema de comandos para gestión en tiempo real
|
|
25
|
+
|
|
26
|
+
## Comandos Disponibles
|
|
27
|
+
|
|
28
|
+
### Comandos Generales de Estadísticas
|
|
29
|
+
- `waf-status` o `waf-stats`: Muestra estadísticas generales del servidor
|
|
30
|
+
- `waf-blocked` o `waf-security`: Muestra estadísticas de seguridad
|
|
31
|
+
- `waf-x-headers`: Muestra reglas de headers X- configuradas
|
|
32
|
+
|
|
33
|
+
### Comandos de Gestión de Reglas
|
|
34
|
+
- `create-x-rule`: Crea una nueva regla de seguridad basada en headers X-
|
|
35
|
+
- `remove-x-rule`: Remueve una regla de seguridad existente
|
|
36
|
+
- `save-rules`: Guarda todas las reglas a un archivo
|
|
37
|
+
- `load-rules`: Carga reglas desde un archivo
|
|
38
|
+
|
|
39
|
+
### Comandos de Gestión de IPs
|
|
40
|
+
- `waf-block-ip`: Bloquea temporalmente una IP
|
|
41
|
+
- `waf-unblock-ip`: Desbloquea una IP temporalmente bloqueada
|
|
42
|
+
- `waf-whitelist`: Agrega una IP a la lista blanca
|
|
43
|
+
- `waf-blacklist`: Agrega una IP a la lista negra
|
|
44
|
+
|
|
45
|
+
## Estadísticas del Servidor
|
|
46
|
+
|
|
47
|
+
### waf-status / waf-stats
|
|
48
|
+
Muestra las estadísticas generales del servidor:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
=== Estadísticas del WAF ===
|
|
52
|
+
Solicitudes procesadas: 15
|
|
53
|
+
Solicitudes procesadas (KB): 2.45 KB
|
|
54
|
+
Respuestas enviadas: 15
|
|
55
|
+
Respuestas enviadas (KB): 15.67 KB
|
|
56
|
+
IPs en lista blanca: 2
|
|
57
|
+
IPs en lista negra: 1
|
|
58
|
+
Reglas de seguridad activas: 3
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Campos de Estadísticas
|
|
62
|
+
- **Solicitudes procesadas**: Número total de solicitudes HTTP procesadas
|
|
63
|
+
- **Solicitudes procesadas (KB)**: Cantidad total de datos recibidos en kilobytes
|
|
64
|
+
- **Respuestas enviadas**: Número total de respuestas HTTP enviadas
|
|
65
|
+
- **Respuestas enviadas (KB)**: Cantidad total de datos enviados en kilobytes
|
|
66
|
+
- **IPs en lista blanca**: Número de IPs que nunca serán bloqueadas
|
|
67
|
+
- **IPs en lista negra**: Número de IPs que siempre serán bloqueadas
|
|
68
|
+
- **Reglas de seguridad activas**: Número de reglas de seguridad activas
|
|
69
|
+
|
|
70
|
+
## Gestión de Reglas X-Headers
|
|
71
|
+
|
|
72
|
+
### Crear Regla (`create-x-rule`)
|
|
73
|
+
Proceso interactivo para crear reglas de seguridad basadas en headers X-:
|
|
74
|
+
|
|
75
|
+
1. **Nombre del header**: Introduce el nombre del header X- (ej: X-Forwarded-For, X-Real-IP)
|
|
76
|
+
2. **Patrón**: Introduce el patrón para coincidir (cadena o expresión regular)
|
|
77
|
+
3. **Acción**: Selecciona la acción a tomar:
|
|
78
|
+
- `1` o `block`: Bloquear solicitudes que coincidan
|
|
79
|
+
- `2` o `log`: Registrar solicitudes que coincidan
|
|
80
|
+
- `3` o `monitor`: Monitorear solicitudes que coincidan
|
|
81
|
+
4. **Razón**: Introduce la razón para la regla (opcional)
|
|
82
|
+
|
|
83
|
+
### Remover Regla (`remove-x-rule`)
|
|
84
|
+
Proceso interactivo para remover reglas existentes:
|
|
85
|
+
1. Se muestra una lista numerada de reglas disponibles
|
|
86
|
+
2. Introduce el número de la regla que deseas remover
|
|
87
|
+
3. La regla se elimina inmediatamente del sistema
|
|
88
|
+
|
|
89
|
+
## Listas de IPs
|
|
90
|
+
|
|
91
|
+
### Whitelist (`waf-whitelist`)
|
|
92
|
+
Agrega una IP a la lista blanca (nunca será bloqueada):
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
> waf-whitelist
|
|
96
|
+
Introduce la IP a agregar a la lista blanca (ej: 192.168.1.100):
|
|
97
|
+
> 192.168.1.100
|
|
98
|
+
IP 192.168.1.100 agregada a la lista blanca.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Blacklist (`waf-blacklist`)
|
|
102
|
+
Agrega una IP a la lista negra (siempre será bloqueada):
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
> waf-blacklist
|
|
106
|
+
Introduce la IP a agregar a la lista negra (ej: 10.0.0.100):
|
|
107
|
+
> 10.0.0.100
|
|
108
|
+
IP 10.0.0.100 agregada a la lista negra.
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Bloqueo Temporal (`waf-block-ip`)
|
|
112
|
+
Bloquea temporalmente una IP:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
> waf-block-ip
|
|
116
|
+
Introduce la IP a bloquear temporalmente (ej: 192.168.1.100):
|
|
117
|
+
> 192.168.1.200
|
|
118
|
+
IP 192.168.1.200 bloqueada temporalmente.
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Persistencia de Reglas
|
|
122
|
+
|
|
123
|
+
### Guardar Reglas (`save-rules`)
|
|
124
|
+
Guarda todas las reglas de seguridad actuales a un archivo JSON:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
> save-rules
|
|
128
|
+
✅ Reglas guardadas exitosamente en: /path/to/waf-rules/waf-rules-timestamp.json
|
|
129
|
+
Total de reglas guardadas: 3
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Cargar Reglas (`load-rules`)
|
|
133
|
+
Carga reglas de seguridad desde un archivo JSON:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
> load-rules
|
|
137
|
+
=== Archivos de Reglas Disponibles ===
|
|
138
|
+
1. waf-rules-1770795262452.json
|
|
139
|
+
|
|
140
|
+
Introduce el número del archivo a cargar (o "cancel" para cancelar):
|
|
141
|
+
> 1
|
|
142
|
+
|
|
143
|
+
¿Deseas reemplazar las reglas actuales? (sí/no):
|
|
144
|
+
> sí
|
|
145
|
+
|
|
146
|
+
✅ Reglas cargadas exitosamente desde: /path/to/waf-rules/waf-rules-1770795262452.json
|
|
147
|
+
Total de reglas cargadas: 3
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Ejemplos de Uso
|
|
151
|
+
|
|
152
|
+
### Ejemplo 1: Crear Regla para Bloquear IPs Internas
|
|
153
|
+
```
|
|
154
|
+
> create-x-rule
|
|
155
|
+
=== Crear Regla de Header X- ===
|
|
156
|
+
Introduce el nombre del header X- (ej: X-Forwarded-For, X-Real-IP):
|
|
157
|
+
> X-Forwarded-For
|
|
158
|
+
Header seleccionado: X-Forwarded-For
|
|
159
|
+
Introduce el patrón para coincidir (cadena o expresión regular):
|
|
160
|
+
> 192.168.
|
|
161
|
+
Selecciona la acción a tomar:
|
|
162
|
+
1. block - Bloquear solicitudes que coincidan
|
|
163
|
+
2. log - Registrar solicitudes que coincidan
|
|
164
|
+
3. monitor - Monitorear solicitudes que coincidan
|
|
165
|
+
Escribe el número o el nombre de la acción:
|
|
166
|
+
> 1
|
|
167
|
+
Acción seleccionada: block
|
|
168
|
+
Introduce la razón para la regla (opcional):
|
|
169
|
+
> Bloquear IPs internas
|
|
170
|
+
✅ Regla de header X- creada exitosamente:
|
|
171
|
+
ID: xheader_x_forwarded_for_1770792842636
|
|
172
|
+
Header: x-forwarded-for
|
|
173
|
+
Patrón: 192.168.
|
|
174
|
+
Acción: block
|
|
175
|
+
Razón: Bloquear IPs internas
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Ejemplo 2: Ver Estadísticas de Seguridad
|
|
179
|
+
```
|
|
180
|
+
> waf-security
|
|
181
|
+
=== Estadísticas de Seguridad del WAF ===
|
|
182
|
+
IPs bloqueadas temporalmente: 2
|
|
183
|
+
Intentos de ataque detectados: 5
|
|
184
|
+
Tipos de ataques detectados: 3
|
|
185
|
+
Registros de seguridad: 10
|
|
186
|
+
|
|
187
|
+
Accesos a rutas (Input/Output):
|
|
188
|
+
GET /: 8 accesos
|
|
189
|
+
POST /api/users: 3 accesos
|
|
190
|
+
GET /api/users: 4 accesos
|
|
191
|
+
|
|
192
|
+
Endpoints más accedidos:
|
|
193
|
+
GET /: 8 hits
|
|
194
|
+
GET /api/users: 4 hits
|
|
195
|
+
POST /api/users: 3 hits
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Ejemplo 3: Agregar IP a Lista Negra
|
|
199
|
+
```
|
|
200
|
+
> waf-blacklist
|
|
201
|
+
Introduce la IP a agregar a la lista negra (ej: 10.0.0.100):
|
|
202
|
+
> 10.0.0.100
|
|
203
|
+
IP 10.0.0.100 agregada a la lista negra.
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Consideraciones de Seguridad
|
|
207
|
+
|
|
208
|
+
- El servidor de administración solo escucha en localhost (127.0.0.1) por defecto
|
|
209
|
+
- Todas las operaciones de bloqueo son inmediatas y afectan al sistema en tiempo real
|
|
210
|
+
- Las reglas de seguridad se aplican antes de que la solicitud llegue a los controladores
|
|
211
|
+
- El sistema de persistencia permite mantener reglas entre reinicios del servidor
|
|
212
|
+
|
|
213
|
+
## Solución de Problemas
|
|
214
|
+
|
|
215
|
+
### Las estadísticas no se actualizan
|
|
216
|
+
- Verifica que el middleware de firewall esté activo en tu servidor
|
|
217
|
+
- Asegúrate de que las solicitudes estén pasando por el sistema de firewall
|
|
218
|
+
|
|
219
|
+
### Las reglas no se aplican
|
|
220
|
+
- Verifica que el firewall esté correctamente integrado en tu pipeline de middlewares
|
|
221
|
+
- Confirma que las reglas se hayan creado correctamente usando `waf-x-headers`
|
|
222
|
+
|
|
223
|
+
## Autor
|
|
224
|
+
|
|
225
|
+
JERK Framework Team
|
|
226
|
+
|
|
227
|
+
## Versión
|
|
228
|
+
|
|
229
|
+
v2.5.8
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Punto de entrada del framework JERK
|
|
3
|
-
* JERK Framework 2.5.
|
|
3
|
+
* JERK Framework 2.5.8
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Mostrar mensaje de versión al iniciar
|
|
@@ -51,10 +51,15 @@ const { ErrorHandler, ValidationError, AuthenticationError, DatabaseError } = re
|
|
|
51
51
|
|
|
52
52
|
// Componentes de caché
|
|
53
53
|
const CacheHooks = require('./lib/cache/CacheHooks');
|
|
54
|
+
|
|
54
55
|
// Componentes del QueryBuilder (v2.3.0) - MODIFICADO PARA USAR QBUILDERJS
|
|
55
56
|
const QueryBuilder = require('qbuilderjs');
|
|
56
57
|
// No hay middleware ni hooks ya que se eliminó la implementación interna
|
|
57
58
|
|
|
59
|
+
// Componentes de sistema de colas (v2.6.0)
|
|
60
|
+
const QueueSystem = require('./lib/queue/QueueSystem');
|
|
61
|
+
const QueueIntegration = require('./lib/queue/integration');
|
|
62
|
+
|
|
58
63
|
|
|
59
64
|
// Exportar todos los componentes del framework
|
|
60
65
|
module.exports = {
|
|
@@ -100,7 +105,7 @@ module.exports = {
|
|
|
100
105
|
// Componentes de modelo (v2.4.0)
|
|
101
106
|
ModelBase,
|
|
102
107
|
ModelManager,
|
|
103
|
-
// Componentes del QueryBuilder (v2.3.0)
|
|
108
|
+
// Componentes del QueryBuilder (v2.3.0)
|
|
104
109
|
QueryBuilder,
|
|
105
110
|
UserModel,
|
|
106
111
|
|
|
@@ -118,6 +123,10 @@ module.exports = {
|
|
|
118
123
|
AuthenticationError,
|
|
119
124
|
DatabaseError,
|
|
120
125
|
|
|
126
|
+
// Componentes de sistema de colas (v2.6.0)
|
|
127
|
+
QueueSystem,
|
|
128
|
+
QueueIntegration,
|
|
129
|
+
|
|
121
130
|
// Componentes de administración (v2.5.7)
|
|
122
131
|
AdminExtension: require('./lib/admin/AdminExtension')
|
|
123
132
|
};
|
|
@@ -130,4 +139,4 @@ const hooksInstance = new HookSystem();
|
|
|
130
139
|
module.exports.hooks = hooksInstance;
|
|
131
140
|
|
|
132
141
|
// Disparar hooks de inicio del framework
|
|
133
|
-
hooksInstance.doAction('framework_init');
|
|
142
|
+
hooksInstance.doAction('framework_init');
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Cliente CLI para JERK Framework Administration Server
|
|
2
|
+
|
|
3
|
+
Cliente de línea de comandos para interactuar con el servidor de administración de JERK Framework. Permite reutilizar comandos y cuenta con autocompletado.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- **Autocompletado**: Presiona TAB para autocompletar comandos conocidos
|
|
8
|
+
- **Historial de comandos**: Accede a comandos previamente utilizados
|
|
9
|
+
- **Reutilización de comandos**: Reutiliza comandos por número o por texto
|
|
10
|
+
- **Conservación de contexto**: Mantiene el historial entre sesiones
|
|
11
|
+
|
|
12
|
+
## Instalación
|
|
13
|
+
|
|
14
|
+
El cliente CLI está incluido en el framework JERK y se puede ejecutar directamente:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
node jerk-admin-client.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
O con parámetros específicos:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
node jerk-admin-client.js --host 127.0.0.1 --port 9999
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Comandos del Cliente
|
|
27
|
+
|
|
28
|
+
Además de los comandos del servidor de administración, el cliente CLI incluye comandos especiales:
|
|
29
|
+
|
|
30
|
+
- `history` - Muestra el historial de comandos
|
|
31
|
+
- `clear` - Limpia la pantalla
|
|
32
|
+
- `re <número>` - Reutiliza el comando número n del historial
|
|
33
|
+
- `re <texto>` - Reutiliza el último comando que contiene el texto
|
|
34
|
+
- `help-cli` - Muestra la ayuda del cliente
|
|
35
|
+
|
|
36
|
+
## Uso
|
|
37
|
+
|
|
38
|
+
1. Inicia el cliente:
|
|
39
|
+
```bash
|
|
40
|
+
node jerk-admin-client.js
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. El cliente se conectará automáticamente al servidor de administración en `localhost:9999`
|
|
44
|
+
|
|
45
|
+
3. Usa los comandos estándar del servidor de administración:
|
|
46
|
+
- `stats` - Ver estadísticas generales
|
|
47
|
+
- `requests` - Ver estadísticas de solicitudes
|
|
48
|
+
- `endpoints` - Ver endpoints más accedidos
|
|
49
|
+
- `routes` - Ver rutas registradas
|
|
50
|
+
- `help` - Ver todos los comandos disponibles
|
|
51
|
+
|
|
52
|
+
4. Usa los comandos especiales del cliente para mejorar la experiencia:
|
|
53
|
+
- `history` para ver comandos anteriores
|
|
54
|
+
- `re 3` para reutilizar el tercer comando del historial
|
|
55
|
+
- `re stats` para reutilizar el último comando que contenía "stats"
|
|
56
|
+
|
|
57
|
+
## Atajos
|
|
58
|
+
|
|
59
|
+
- Presiona `↑` y `↓` para navegar por el historial de comandos
|
|
60
|
+
- Presiona `TAB` para autocompletar comandos
|
|
61
|
+
- Presiona `Ctrl+C` para salir del cliente
|
|
62
|
+
|
|
63
|
+
## Configuración
|
|
64
|
+
|
|
65
|
+
Por defecto, el cliente intenta conectarse a `localhost:9999`. Puedes especificar un host y puerto diferente usando los argumentos `--host` y `--port`.
|
|
66
|
+
|
|
67
|
+
## Archivo de Historial
|
|
68
|
+
|
|
69
|
+
El cliente guarda el historial de comandos en `~/.jerk_admin_history` para conservarlo entre sesiones.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jerkjs/admin-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Cliente CLI para interactuar con el servidor de administración de JERK Framework",
|
|
5
|
+
"main": "jerk-admin-client.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"jerk-admin": "./jerk-admin-client.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node jerk-admin-client.js",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"jerkjs",
|
|
15
|
+
"admin",
|
|
16
|
+
"cli",
|
|
17
|
+
"client",
|
|
18
|
+
"framework"
|
|
19
|
+
],
|
|
20
|
+
"author": "JERK Framework Team",
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"dependencies": {}
|
|
23
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cliente CLI para interactuar con el servidor de administración de JERK Framework
|
|
5
|
+
* Permite reutilizar comandos y tiene autocompletado
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const net = require('net');
|
|
9
|
+
const readline = require('readline');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
// Configuración por defecto
|
|
14
|
+
const DEFAULT_HOST = 'localhost';
|
|
15
|
+
const DEFAULT_PORT = 9999;
|
|
16
|
+
|
|
17
|
+
// Historial de comandos
|
|
18
|
+
let commandHistory = [];
|
|
19
|
+
const HISTORY_FILE = path.join(require('os').homedir(), '.jerk_admin_history');
|
|
20
|
+
|
|
21
|
+
// Cargar historial de comandos si existe
|
|
22
|
+
if (fs.existsSync(HISTORY_FILE)) {
|
|
23
|
+
try {
|
|
24
|
+
const historyData = fs.readFileSync(HISTORY_FILE, 'utf8');
|
|
25
|
+
commandHistory = JSON.parse(historyData);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('Error al cargar el historial:', error.message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Comandos conocidos para autocompletado
|
|
32
|
+
const knownCommands = [
|
|
33
|
+
'help',
|
|
34
|
+
'stats',
|
|
35
|
+
'statistics',
|
|
36
|
+
'requests',
|
|
37
|
+
'endpoints',
|
|
38
|
+
'routes',
|
|
39
|
+
'active',
|
|
40
|
+
'version',
|
|
41
|
+
'status',
|
|
42
|
+
'cache',
|
|
43
|
+
'cache-stats',
|
|
44
|
+
'cache-clear',
|
|
45
|
+
'cache-info',
|
|
46
|
+
'sysinfo',
|
|
47
|
+
'system',
|
|
48
|
+
'resources',
|
|
49
|
+
'time',
|
|
50
|
+
'date',
|
|
51
|
+
'quit',
|
|
52
|
+
'exit'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
// Función para guardar el historial
|
|
56
|
+
function saveHistory() {
|
|
57
|
+
try {
|
|
58
|
+
fs.writeFileSync(HISTORY_FILE, JSON.stringify(commandHistory, null, 2));
|
|
59
|
+
} catch (error) {
|
|
60
|
+
console.error('Error al guardar el historial:', error.message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Función para autocompletar comandos
|
|
65
|
+
function completer(line) {
|
|
66
|
+
const hits = knownCommands.filter(cmd => cmd.startsWith(line));
|
|
67
|
+
return [hits.length ? hits : knownCommands, line];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Función para crear el cliente
|
|
71
|
+
function createClient(host = DEFAULT_HOST, port = DEFAULT_PORT) {
|
|
72
|
+
const client = new net.Socket();
|
|
73
|
+
|
|
74
|
+
// Conectar al servidor de administración
|
|
75
|
+
client.connect(port, host, () => {
|
|
76
|
+
console.log(`Conectado al servidor de administración en ${host}:${port}`);
|
|
77
|
+
console.log('Escribe "help" para ver los comandos disponibles o "quit" para salir\n');
|
|
78
|
+
|
|
79
|
+
// Configurar readline con autocompletado
|
|
80
|
+
const rl = readline.createInterface({
|
|
81
|
+
input: process.stdin,
|
|
82
|
+
output: process.stdout,
|
|
83
|
+
completer: completer,
|
|
84
|
+
history: commandHistory
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Mostrar historial de comandos recientes
|
|
88
|
+
if (commandHistory.length > 0) {
|
|
89
|
+
console.log(`Comandos recientes: ${commandHistory.slice(-5).join(', ')}\n`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Función para manejar la entrada del usuario
|
|
93
|
+
function handleInput() {
|
|
94
|
+
rl.question('> ', (input) => {
|
|
95
|
+
const command = input.trim();
|
|
96
|
+
|
|
97
|
+
if (command.toLowerCase() === 'quit' || command.toLowerCase() === 'exit') {
|
|
98
|
+
console.log('Desconectando del servidor...');
|
|
99
|
+
client.end();
|
|
100
|
+
rl.close();
|
|
101
|
+
saveHistory();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (command.toLowerCase() === 'history') {
|
|
106
|
+
console.log('Historial de comandos:');
|
|
107
|
+
commandHistory.forEach((cmd, index) => {
|
|
108
|
+
console.log(`${index + 1}. ${cmd}`);
|
|
109
|
+
});
|
|
110
|
+
handleInput();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (command.toLowerCase() === 'clear') {
|
|
115
|
+
console.clear();
|
|
116
|
+
handleInput();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (command.toLowerCase() === 'help-cli') {
|
|
121
|
+
console.log('\n--- Comandos del Cliente CLI ---');
|
|
122
|
+
console.log('help-cli - Muestra esta ayuda');
|
|
123
|
+
console.log('history - Muestra el historial de comandos');
|
|
124
|
+
console.log('clear - Limpia la pantalla');
|
|
125
|
+
console.log('re <número> - Reutiliza el comando número n del historial');
|
|
126
|
+
console.log('re <texto> - Reutiliza el último comando que contiene el texto');
|
|
127
|
+
console.log('-----------------------------\n');
|
|
128
|
+
handleInput();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Comando para reutilizar comandos del historial
|
|
133
|
+
if (command.toLowerCase().startsWith('re ')) {
|
|
134
|
+
const arg = command.substring(3).trim();
|
|
135
|
+
|
|
136
|
+
if (/^\d+$/.test(arg)) {
|
|
137
|
+
// Reutilizar por número
|
|
138
|
+
const index = parseInt(arg) - 1;
|
|
139
|
+
if (index >= 0 && index < commandHistory.length) {
|
|
140
|
+
const reusedCmd = commandHistory[index];
|
|
141
|
+
console.log(`Reutilizando comando: ${reusedCmd}`);
|
|
142
|
+
client.write(reusedCmd + '\n');
|
|
143
|
+
if (!commandHistory.includes(reusedCmd)) {
|
|
144
|
+
commandHistory.push(reusedCmd);
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
console.log(`Número de comando inválido: ${arg}`);
|
|
148
|
+
handleInput();
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
// Reutilizar por texto
|
|
152
|
+
const matchingCmd = commandHistory.reverse().find(cmd => cmd.includes(arg));
|
|
153
|
+
commandHistory.reverse(); // Restaurar orden original
|
|
154
|
+
|
|
155
|
+
if (matchingCmd) {
|
|
156
|
+
console.log(`Reutilizando comando: ${matchingCmd}`);
|
|
157
|
+
client.write(matchingCmd + '\n');
|
|
158
|
+
} else {
|
|
159
|
+
console.log(`No se encontró comando que contenga: ${arg}`);
|
|
160
|
+
handleInput();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} else if (command) {
|
|
164
|
+
// Enviar comando al servidor
|
|
165
|
+
client.write(command + '\n');
|
|
166
|
+
|
|
167
|
+
// Agregar al historial si no está repetido
|
|
168
|
+
if (!commandHistory.includes(command)) {
|
|
169
|
+
commandHistory.push(command);
|
|
170
|
+
// Mantener solo los últimos 100 comandos
|
|
171
|
+
if (commandHistory.length > 100) {
|
|
172
|
+
commandHistory = commandHistory.slice(-100);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
handleInput();
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Iniciar la interacción
|
|
182
|
+
handleInput();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Manejar datos recibidos del servidor
|
|
186
|
+
client.on('data', (data) => {
|
|
187
|
+
const output = data.toString();
|
|
188
|
+
process.stdout.write(output);
|
|
189
|
+
|
|
190
|
+
// Si la salida termina con el prompt, significa que el comando terminó
|
|
191
|
+
if (output.endsWith('> ')) {
|
|
192
|
+
// No hacer nada, dejar que readline continúe
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Manejar errores
|
|
197
|
+
client.on('error', (error) => {
|
|
198
|
+
console.error(`Error de conexión: ${error.message}`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Manejar cierre de conexión
|
|
203
|
+
client.on('close', () => {
|
|
204
|
+
console.log('\nConexión cerrada');
|
|
205
|
+
process.exit(0);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Mostrar ayuda
|
|
210
|
+
function showHelp() {
|
|
211
|
+
console.log(`
|
|
212
|
+
Cliente CLI para JERK Framework Administration Server
|
|
213
|
+
|
|
214
|
+
Uso: node jerk-admin-client.js [opciones]
|
|
215
|
+
|
|
216
|
+
Opciones:
|
|
217
|
+
-h, --host HOST Host del servidor (por defecto: ${DEFAULT_HOST})
|
|
218
|
+
-p, --port PORT Puerto del servidor (por defecto: ${DEFAULT_PORT})
|
|
219
|
+
--help Mostrar esta ayuda
|
|
220
|
+
|
|
221
|
+
Comandos especiales del cliente:
|
|
222
|
+
history Mostrar historial de comandos
|
|
223
|
+
clear Limpiar la pantalla
|
|
224
|
+
re <número> Reutilizar comando por número
|
|
225
|
+
re <texto> Reutilizar último comando que contiene texto
|
|
226
|
+
help-cli Mostrar ayuda del cliente
|
|
227
|
+
|
|
228
|
+
Ejemplos:
|
|
229
|
+
node jerk-admin-client.js
|
|
230
|
+
node jerk-admin-client.js --host 127.0.0.1 --port 9999
|
|
231
|
+
`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Parsear argumentos
|
|
235
|
+
const args = process.argv.slice(2);
|
|
236
|
+
let host = DEFAULT_HOST;
|
|
237
|
+
let port = DEFAULT_PORT;
|
|
238
|
+
|
|
239
|
+
for (let i = 0; i < args.length; i++) {
|
|
240
|
+
if (args[i] === '--help' || args[i] === '-h') {
|
|
241
|
+
showHelp();
|
|
242
|
+
process.exit(0);
|
|
243
|
+
} else if (args[i] === '--host' || args[i] === '-h') {
|
|
244
|
+
host = args[++i];
|
|
245
|
+
} else if (args[i] === '--port' || args[i] === '-p') {
|
|
246
|
+
port = parseInt(args[++i]);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Validar puerto
|
|
251
|
+
if (isNaN(port) || port <= 0 || port > 65535) {
|
|
252
|
+
console.error(`Puerto inválido: ${port}`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Iniciar el cliente
|
|
257
|
+
createClient(host, port);
|