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,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;
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Módulo de Generación de Controladores para la Extensión de Administración de JERK Framework
|
|
3
|
+
* Módulo personalizado para crear controladores de manera interactiva
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class ControllerGeneratorModule {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor del módulo de generación de controladores
|
|
12
|
+
* @param {Object} adminExtension - Instancia de la extensión de administración
|
|
13
|
+
*/
|
|
14
|
+
constructor(adminExtension) {
|
|
15
|
+
this.adminExtension = adminExtension;
|
|
16
|
+
this.name = 'Controller Generator Module';
|
|
17
|
+
this.description = 'Módulo para crear controladores de manera interactiva';
|
|
18
|
+
this.commands = ['generate-controller', 'gen-ctrl', 'new-ctrl'];
|
|
19
|
+
|
|
20
|
+
// Estado para el proceso interactivo
|
|
21
|
+
this.currentProcess = new Map(); // Almacena el estado de generación por socket
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Manejador para los comandos del módulo de generación de controladores
|
|
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 'generate-controller':
|
|
32
|
+
case 'gen-ctrl':
|
|
33
|
+
case 'new-ctrl':
|
|
34
|
+
this.startControllerGeneration(socket);
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
socket.write(`Comando desconocido para el módulo de generación de controladores: ${command}\n`);
|
|
38
|
+
socket.write(`Comandos disponibles: generate-controller, gen-ctrl, new-ctrl\n\n`);
|
|
39
|
+
socket.write(`> `);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Inicia el proceso interactivo de generación de controlador
|
|
45
|
+
* @param {Object} socket - Socket de la conexión
|
|
46
|
+
*/
|
|
47
|
+
startControllerGeneration(socket) {
|
|
48
|
+
const sessionId = this.getSessionId(socket);
|
|
49
|
+
|
|
50
|
+
// Inicializar el estado de la sesión
|
|
51
|
+
this.currentProcess.set(sessionId, {
|
|
52
|
+
step: 'name',
|
|
53
|
+
controllerData: {}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
socket.write('\n=== Generador de Controladores ===\n');
|
|
57
|
+
socket.write('Por favor, introduce el nombre del controlador (sin la palabra "Controller"):\n');
|
|
58
|
+
socket.write('(Ej: "User", "Product", "Home")\n');
|
|
59
|
+
socket.write('Para cancelar, escribe "cancel"\n');
|
|
60
|
+
socket.write('> ');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Obtiene un ID único para la sesión del socket
|
|
65
|
+
* @param {Object} socket - Socket de la conexión
|
|
66
|
+
* @returns {string} - ID de sesión
|
|
67
|
+
*/
|
|
68
|
+
getSessionId(socket) {
|
|
69
|
+
// Usar la dirección remota y puerto como identificador único
|
|
70
|
+
return `${socket.remoteAddress}:${socket.remotePort}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Procesa la entrada del usuario durante el proceso interactivo
|
|
75
|
+
* @param {Object} socket - Socket de la conexión
|
|
76
|
+
* @param {string} input - Entrada del usuario
|
|
77
|
+
*/
|
|
78
|
+
processInput(socket, input) {
|
|
79
|
+
const sessionId = this.getSessionId(socket);
|
|
80
|
+
const processState = this.currentProcess.get(sessionId);
|
|
81
|
+
|
|
82
|
+
if (!processState) {
|
|
83
|
+
socket.write('No hay proceso activo. Usa "generate-controller" para iniciar.\n> ');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const userInput = input.trim();
|
|
88
|
+
|
|
89
|
+
if (userInput.toLowerCase() === 'cancel') {
|
|
90
|
+
this.cancelProcess(socket, sessionId);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
switch (processState.step) {
|
|
95
|
+
case 'name':
|
|
96
|
+
this.handleControllerName(socket, sessionId, userInput);
|
|
97
|
+
break;
|
|
98
|
+
case 'methods':
|
|
99
|
+
this.handleMethodsSelection(socket, sessionId, userInput);
|
|
100
|
+
break;
|
|
101
|
+
case 'confirm':
|
|
102
|
+
this.handleConfirmation(socket, sessionId, userInput);
|
|
103
|
+
break;
|
|
104
|
+
case 'path':
|
|
105
|
+
this.handleControllerPath(socket, sessionId, userInput);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Maneja la entrada del nombre del controlador
|
|
112
|
+
* @param {Object} socket - Socket de la conexión
|
|
113
|
+
* @param {string} sessionId - ID de la sesión
|
|
114
|
+
* @param {string} name - Nombre del controlador
|
|
115
|
+
*/
|
|
116
|
+
handleControllerName(socket, sessionId, name) {
|
|
117
|
+
if (!name) {
|
|
118
|
+
socket.write('El nombre no puede estar vacío. Por favor, introduce un nombre válido:\n> ');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Validar nombre (solo letras, números y guiones bajos)
|
|
123
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
124
|
+
socket.write('Nombre inválido. Usa solo letras, números y guiones bajos, comenzando con una letra o guión bajo:\n> ');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const processState = this.currentProcess.get(sessionId);
|
|
129
|
+
processState.controllerData.name = name;
|
|
130
|
+
processState.step = 'methods';
|
|
131
|
+
|
|
132
|
+
socket.write(`\nNombre del controlador: ${name}Controller\n`);
|
|
133
|
+
socket.write('\nSelecciona los métodos que deseas incluir (separados por comas):\n');
|
|
134
|
+
socket.write('Opciones disponibles:\n');
|
|
135
|
+
socket.write(' 1. index - Método para mostrar lista de elementos\n');
|
|
136
|
+
socket.write(' 2. show - Método para mostrar un elemento específico\n');
|
|
137
|
+
socket.write(' 3. create - Método para crear un nuevo elemento\n');
|
|
138
|
+
socket.write(' 4. update - Método para actualizar un elemento\n');
|
|
139
|
+
socket.write(' 5. delete - Método para eliminar un elemento\n');
|
|
140
|
+
socket.write(' 6. All - Todos los métodos anteriores\n');
|
|
141
|
+
socket.write('\nEjemplos: "1,2,3" o "index,show,create" o "All"\n> ');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Maneja la selección de métodos
|
|
146
|
+
* @param {Object} socket - Socket de la conexión
|
|
147
|
+
* @param {string} sessionId - ID de la sesión
|
|
148
|
+
* @param {string} selection - Selección de métodos
|
|
149
|
+
*/
|
|
150
|
+
handleMethodsSelection(socket, sessionId, selection) {
|
|
151
|
+
const processState = this.currentProcess.get(sessionId);
|
|
152
|
+
const methodsMap = {
|
|
153
|
+
'1': 'index', '2': 'show', '3': 'create', '4': 'update', '5': 'delete'
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
let selectedMethods = [];
|
|
157
|
+
|
|
158
|
+
if (selection.toLowerCase() === 'all') {
|
|
159
|
+
selectedMethods = ['index', 'show', 'create', 'update', 'delete'];
|
|
160
|
+
} else {
|
|
161
|
+
// Separar por comas y procesar cada selección
|
|
162
|
+
const selections = selection.split(',').map(s => s.trim());
|
|
163
|
+
|
|
164
|
+
for (const sel of selections) {
|
|
165
|
+
if (methodsMap[sel]) {
|
|
166
|
+
selectedMethods.push(methodsMap[sel]);
|
|
167
|
+
} else if (['index', 'show', 'create', 'update', 'delete'].includes(sel)) {
|
|
168
|
+
selectedMethods.push(sel);
|
|
169
|
+
} else {
|
|
170
|
+
socket.write(`Selección inválida: ${sel}. Por favor, selecciona métodos válidos:\n> `);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Eliminar duplicados
|
|
177
|
+
selectedMethods = [...new Set(selectedMethods)];
|
|
178
|
+
|
|
179
|
+
processState.controllerData.methods = selectedMethods;
|
|
180
|
+
processState.step = 'path';
|
|
181
|
+
|
|
182
|
+
socket.write(`\nMétodos seleccionados: ${selectedMethods.join(', ')}\n`);
|
|
183
|
+
socket.write('\nIndica la ruta donde deseas crear el archivo del controlador:\n');
|
|
184
|
+
socket.write('(Ruta relativa desde la raíz del proyecto, ej: "./controllers/", "./src/controllers/")\n');
|
|
185
|
+
socket.write('Deja vacío para usar "./controllers/" por defecto:\n> ');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Maneja la selección de la ruta del controlador
|
|
190
|
+
* @param {Object} socket - Socket de la conexión
|
|
191
|
+
* @param {string} sessionId - ID de la sesión
|
|
192
|
+
* @param {string} pathInput - Ruta ingresada
|
|
193
|
+
*/
|
|
194
|
+
handleControllerPath(socket, sessionId, pathInput) {
|
|
195
|
+
const processState = this.currentProcess.get(sessionId);
|
|
196
|
+
|
|
197
|
+
// Usar la ruta por defecto si no se proporciona ninguna
|
|
198
|
+
const controllerPath = pathInput.trim() || './controllers/';
|
|
199
|
+
|
|
200
|
+
// Asegurarse de que termine con '/'
|
|
201
|
+
const normalizedPath = controllerPath.endsWith('/') ? controllerPath : controllerPath + '/';
|
|
202
|
+
|
|
203
|
+
processState.controllerData.path = normalizedPath;
|
|
204
|
+
processState.step = 'confirm';
|
|
205
|
+
|
|
206
|
+
socket.write(`\nRuta del controlador: ${normalizedPath}\n`);
|
|
207
|
+
this.showControllerPreview(socket, processState.controllerData);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Muestra una vista previa del controlador que se va a generar
|
|
212
|
+
* @param {Object} socket - Socket de la conexión
|
|
213
|
+
* @param {Object} controllerData - Datos del controlador
|
|
214
|
+
*/
|
|
215
|
+
showControllerPreview(socket, controllerData) {
|
|
216
|
+
socket.write('\n=== Vista Previa del Controlador ===\n');
|
|
217
|
+
socket.write(`Nombre del archivo: ${controllerData.name}Controller.js\n\n`);
|
|
218
|
+
|
|
219
|
+
let preview = `const ControllerBase = require('../../index.js').ControllerBase;\n\n`;
|
|
220
|
+
preview += `class ${controllerData.name}Controller extends ControllerBase {\n`;
|
|
221
|
+
|
|
222
|
+
for (const method of controllerData.methods) {
|
|
223
|
+
preview += this.generateMethodSkeleton(method, controllerData.name);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
preview += `}\n\n`;
|
|
227
|
+
preview += `module.exports = new ${controllerData.name}Controller();\n`;
|
|
228
|
+
|
|
229
|
+
socket.write(preview);
|
|
230
|
+
socket.write('\n¿Deseas crear este controlador? (sí/no):\n> ');
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Genera el esqueleto de un método
|
|
235
|
+
* @param {string} method - Nombre del método
|
|
236
|
+
* @param {string} controllerName - Nombre del controlador
|
|
237
|
+
* @returns {string} - Código del método
|
|
238
|
+
*/
|
|
239
|
+
generateMethodSkeleton(method, controllerName) {
|
|
240
|
+
let skeleton = '';
|
|
241
|
+
|
|
242
|
+
switch (method) {
|
|
243
|
+
case 'index':
|
|
244
|
+
skeleton += ` async index(req, res) {\n`;
|
|
245
|
+
skeleton += ` try {\n`;
|
|
246
|
+
skeleton += ` // Lógica para obtener y mostrar una lista de ${controllerName.toLowerCase()}s\n`;
|
|
247
|
+
skeleton += ` const items = await this.loadModel('${controllerName}Model').then(model => model.find({}));\n`;
|
|
248
|
+
skeleton += ` \n`;
|
|
249
|
+
skeleton += ` res.render('${controllerName.toLowerCase()}/index', { \n`;
|
|
250
|
+
skeleton += ` title: '${controllerName}s',\n`;
|
|
251
|
+
skeleton += ` items\n`;
|
|
252
|
+
skeleton += ` });\n`;
|
|
253
|
+
skeleton += ` } catch (error) {\n`;
|
|
254
|
+
skeleton += ` console.error('Error en el método index:', error);\n`;
|
|
255
|
+
skeleton += ` res.writeHead(500, { 'Content-Type': 'application/json' });\n`;
|
|
256
|
+
skeleton += ` res.end(JSON.stringify({ error: 'Error interno del servidor' }));\n`;
|
|
257
|
+
skeleton += ` }\n`;
|
|
258
|
+
skeleton += ` }\n\n`;
|
|
259
|
+
break;
|
|
260
|
+
|
|
261
|
+
case 'show':
|
|
262
|
+
skeleton += ` async show(req, res) {\n`;
|
|
263
|
+
skeleton += ` try {\n`;
|
|
264
|
+
skeleton += ` const id = req.params.id;\n`;
|
|
265
|
+
skeleton += ` // Lógica para obtener y mostrar un ${controllerName.toLowerCase()} específico\n`;
|
|
266
|
+
skeleton += ` const item = await this.loadModel('${controllerName}Model').then(model => model.findOne({ id: parseInt(id) }));\n`;
|
|
267
|
+
skeleton += ` \n`;
|
|
268
|
+
skeleton += ` if (!item) {\n`;
|
|
269
|
+
skeleton += ` res.writeHead(404, { 'Content-Type': 'application/json' });\n`;
|
|
270
|
+
skeleton += ` res.end(JSON.stringify({ error: '${controllerName} no encontrado' }));\n`;
|
|
271
|
+
skeleton += ` return;\n`;
|
|
272
|
+
skeleton += ` }\n`;
|
|
273
|
+
skeleton += ` \n`;
|
|
274
|
+
skeleton += ` res.render('${controllerName.toLowerCase()}/show', { \n`;
|
|
275
|
+
skeleton += ` title: '${controllerName} #' + id,\n`;
|
|
276
|
+
skeleton += ` item\n`;
|
|
277
|
+
skeleton += ` });\n`;
|
|
278
|
+
skeleton += ` } catch (error) {\n`;
|
|
279
|
+
skeleton += ` console.error('Error en el método show:', error);\n`;
|
|
280
|
+
skeleton += ` res.writeHead(500, { 'Content-Type': 'application/json' });\n`;
|
|
281
|
+
skeleton += ` res.end(JSON.stringify({ error: 'Error interno del servidor' }));\n`;
|
|
282
|
+
skeleton += ` }\n`;
|
|
283
|
+
skeleton += ` }\n\n`;
|
|
284
|
+
break;
|
|
285
|
+
|
|
286
|
+
case 'create':
|
|
287
|
+
skeleton += ` async create(req, res) {\n`;
|
|
288
|
+
skeleton += ` try {\n`;
|
|
289
|
+
skeleton += ` // Lógica para crear un nuevo ${controllerName.toLowerCase()}\n`;
|
|
290
|
+
skeleton += ` const data = req.body;\n`;
|
|
291
|
+
skeleton += ` const newItem = await this.loadModel('${controllerName}Model').then(model => model.create(data));\n`;
|
|
292
|
+
skeleton += ` \n`;
|
|
293
|
+
skeleton += ` res.writeHead(201, { 'Content-Type': 'application/json' });\n`;
|
|
294
|
+
skeleton += ` res.end(JSON.stringify({ success: true, data: newItem }));\n`;
|
|
295
|
+
skeleton += ` } catch (error) {\n`;
|
|
296
|
+
skeleton += ` console.error('Error en el método create:', error);\n`;
|
|
297
|
+
skeleton += ` res.writeHead(400, { 'Content-Type': 'application/json' });\n`;
|
|
298
|
+
skeleton += ` res.end(JSON.stringify({ error: error.message }));\n`;
|
|
299
|
+
skeleton += ` }\n`;
|
|
300
|
+
skeleton += ` }\n\n`;
|
|
301
|
+
break;
|
|
302
|
+
|
|
303
|
+
case 'update':
|
|
304
|
+
skeleton += ` async update(req, res) {\n`;
|
|
305
|
+
skeleton += ` try {\n`;
|
|
306
|
+
skeleton += ` const id = req.params.id;\n`;
|
|
307
|
+
skeleton += ` const data = req.body;\n`;
|
|
308
|
+
skeleton += ` // Lógica para actualizar un ${controllerName.toLowerCase()} existente\n`;
|
|
309
|
+
skeleton += ` const result = await this.loadModel('${controllerName}Model').then(model => model.update({ id: parseInt(id) }, data));\n`;
|
|
310
|
+
skeleton += ` \n`;
|
|
311
|
+
skeleton += ` res.writeHead(200, { 'Content-Type': 'application/json' });\n`;
|
|
312
|
+
skeleton += ` res.end(JSON.stringify({ success: true, data: result }));\n`;
|
|
313
|
+
skeleton += ` } catch (error) {\n`;
|
|
314
|
+
skeleton += ` console.error('Error en el método update:', error);\n`;
|
|
315
|
+
skeleton += ` res.writeHead(400, { 'Content-Type': 'application/json' });\n`;
|
|
316
|
+
skeleton += ` res.end(JSON.stringify({ error: error.message }));\n`;
|
|
317
|
+
skeleton += ` }\n`;
|
|
318
|
+
skeleton += ` }\n\n`;
|
|
319
|
+
break;
|
|
320
|
+
|
|
321
|
+
case 'delete':
|
|
322
|
+
skeleton += ` async delete(req, res) {\n`;
|
|
323
|
+
skeleton += ` try {\n`;
|
|
324
|
+
skeleton += ` const id = req.params.id;\n`;
|
|
325
|
+
skeleton += ` // Lógica para eliminar un ${controllerName.toLowerCase()}\n`;
|
|
326
|
+
skeleton += ` const result = await this.loadModel('${controllerName}Model').then(model => model.delete({ id: parseInt(id) }));\n`;
|
|
327
|
+
skeleton += ` \n`;
|
|
328
|
+
skeleton += ` res.writeHead(200, { 'Content-Type': 'application/json' });\n`;
|
|
329
|
+
skeleton += ` res.end(JSON.stringify({ success: true, message: '${controllerName} eliminado correctamente' }));\n`;
|
|
330
|
+
skeleton += ` } catch (error) {\n`;
|
|
331
|
+
skeleton += ` console.error('Error en el método delete:', error);\n`;
|
|
332
|
+
skeleton += ` res.writeHead(400, { 'Content-Type': 'application/json' });\n`;
|
|
333
|
+
skeleton += ` res.end(JSON.stringify({ error: error.message }));\n`;
|
|
334
|
+
skeleton += ` }\n`;
|
|
335
|
+
skeleton += ` }\n\n`;
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return skeleton;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Maneja la confirmación de creación del controlador
|
|
344
|
+
* @param {Object} socket - Socket de la conexión
|
|
345
|
+
* @param {string} sessionId - ID de la sesión
|
|
346
|
+
* @param {string} confirmation - Confirmación del usuario
|
|
347
|
+
*/
|
|
348
|
+
handleConfirmation(socket, sessionId, confirmation) {
|
|
349
|
+
const processState = this.currentProcess.get(sessionId);
|
|
350
|
+
|
|
351
|
+
if (confirmation.toLowerCase() === 'sí' || confirmation.toLowerCase() === 'si' || confirmation.toLowerCase() === 'yes') {
|
|
352
|
+
this.createControllerFile(socket, processState.controllerData);
|
|
353
|
+
} else {
|
|
354
|
+
socket.write('\nGeneración del controlador cancelada.\n> ');
|
|
355
|
+
this.currentProcess.delete(sessionId);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Crea el archivo del controlador
|
|
361
|
+
* @param {Object} socket - Socket de la conexión
|
|
362
|
+
* @param {Object} controllerData - Datos del controlador
|
|
363
|
+
*/
|
|
364
|
+
createControllerFile(socket, controllerData) {
|
|
365
|
+
const { name, methods, path: controllerPath } = controllerData;
|
|
366
|
+
|
|
367
|
+
// Crear el contenido del archivo
|
|
368
|
+
let content = `const ControllerBase = require('../../index.js').ControllerBase;\n\n`;
|
|
369
|
+
content += `class ${name}Controller extends ControllerBase {\n`;
|
|
370
|
+
|
|
371
|
+
for (const method of methods) {
|
|
372
|
+
content += this.generateMethodSkeleton(method, name);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
content += `}\n\n`;
|
|
376
|
+
content += `module.exports = new ${name}Controller();\n`;
|
|
377
|
+
|
|
378
|
+
// Crear directorio si no existe
|
|
379
|
+
const fullPath = path.join(process.cwd(), controllerPath);
|
|
380
|
+
if (!fs.existsSync(fullPath)) {
|
|
381
|
+
fs.mkdirSync(fullPath, { recursive: true });
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Ruta completa del archivo
|
|
385
|
+
const filePath = path.join(fullPath, `${name}Controller.js`);
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
// Escribir el archivo
|
|
389
|
+
fs.writeFileSync(filePath, content);
|
|
390
|
+
|
|
391
|
+
socket.write(`\n✅ Controlador "${name}Controller" creado exitosamente en:\n${filePath}\n`);
|
|
392
|
+
socket.write(`\nMétodos incluidos: ${methods.join(', ')}\n`);
|
|
393
|
+
socket.write('\n> ');
|
|
394
|
+
} catch (error) {
|
|
395
|
+
socket.write(`\n❌ Error al crear el archivo: ${error.message}\n> `);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Limpiar el estado
|
|
399
|
+
const sessionId = this.getSessionId(socket);
|
|
400
|
+
this.currentProcess.delete(sessionId);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Cancela el proceso de generación
|
|
405
|
+
* @param {Object} socket - Socket de la conexión
|
|
406
|
+
* @param {string} sessionId - ID de la sesión
|
|
407
|
+
*/
|
|
408
|
+
cancelProcess(socket, sessionId) {
|
|
409
|
+
this.currentProcess.delete(sessionId);
|
|
410
|
+
socket.write('\nProceso cancelado.\n> ');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
module.exports = ControllerGeneratorModule;
|