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
|
@@ -168,29 +168,31 @@ class AdminExtension {
|
|
|
168
168
|
loadCustomModules() {
|
|
169
169
|
const fs = require('fs');
|
|
170
170
|
const path = require('path');
|
|
171
|
-
|
|
171
|
+
|
|
172
172
|
try {
|
|
173
173
|
const modulesDir = path.join(__dirname, 'modules');
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
if (fs.existsSync(modulesDir)) {
|
|
176
176
|
const files = fs.readdirSync(modulesDir);
|
|
177
|
-
|
|
177
|
+
|
|
178
178
|
for (const file of files) {
|
|
179
179
|
if (file.endsWith('.js') && file !== 'index.js') {
|
|
180
180
|
try {
|
|
181
181
|
const moduleName = file.replace('.js', '');
|
|
182
|
-
const ModuleClass = require(path.join(modulesDir, file));
|
|
183
182
|
|
|
183
|
+
const ModuleClass = require(path.join(modulesDir, file));
|
|
184
|
+
|
|
184
185
|
if (typeof ModuleClass === 'function') {
|
|
185
186
|
const moduleInstance = new ModuleClass(this);
|
|
186
|
-
|
|
187
|
+
|
|
187
188
|
this.modules.set(moduleName.toLowerCase(), {
|
|
188
189
|
name: moduleInstance.name,
|
|
189
190
|
description: moduleInstance.description,
|
|
190
191
|
commands: moduleInstance.commands,
|
|
191
|
-
handler: (command, socket) => moduleInstance.handleCommand(command, socket)
|
|
192
|
+
handler: (command, socket) => moduleInstance.handleCommand(command, socket),
|
|
193
|
+
instance: moduleInstance // Mantener referencia a la instancia para manejo interactivo
|
|
192
194
|
});
|
|
193
|
-
|
|
195
|
+
|
|
194
196
|
console.log(`Módulo '${moduleName}' cargado exitosamente.`);
|
|
195
197
|
}
|
|
196
198
|
} catch (moduleError) {
|
|
@@ -233,8 +235,18 @@ class AdminExtension {
|
|
|
233
235
|
break;
|
|
234
236
|
case 'status':
|
|
235
237
|
socket.write(`\nEstado del servidor:\n`);
|
|
236
|
-
socket.write(`- Puerto: ${this.port}\n`);
|
|
237
|
-
socket.write(`- Host: ${this.host}\n`);
|
|
238
|
+
socket.write(`- Puerto del servidor de administración: ${this.port}\n`);
|
|
239
|
+
socket.write(`- Host del servidor de administración: ${this.host}\n`);
|
|
240
|
+
|
|
241
|
+
// Mostrar información del servidor principal si está disponible
|
|
242
|
+
if (this.frameworkInstance) {
|
|
243
|
+
socket.write(`- Puerto del servidor principal: ${this.frameworkInstance.port || 'desconocido'}\n`);
|
|
244
|
+
socket.write(`- Host del servidor principal: ${this.frameworkInstance.host || 'desconocido'}\n`);
|
|
245
|
+
} else {
|
|
246
|
+
socket.write(`- Puerto del servidor principal: desconocido\n`);
|
|
247
|
+
socket.write(`- Host del servidor principal: desconocido\n`);
|
|
248
|
+
}
|
|
249
|
+
|
|
238
250
|
socket.write(`- Clientes conectados: ${this.clients.size}\n`);
|
|
239
251
|
socket.write(`- Rutas registradas: ${this.registeredRoutes.length}\n`);
|
|
240
252
|
socket.write(`- Rutas activas: ${this.activeRoutes.size}\n\n`);
|
|
@@ -271,10 +283,10 @@ class AdminExtension {
|
|
|
271
283
|
|
|
272
284
|
socket.write(`Comandos disponibles:\n`);
|
|
273
285
|
for (const [name, module] of this.modules) {
|
|
274
|
-
socket.write(` ${module.commands.join(', ')} - ${module.description}\n`);
|
|
286
|
+
socket.write(` \x1b[32m${module.commands.join(', ')}\x1b[0m - ${module.description}\n`);
|
|
275
287
|
}
|
|
276
|
-
socket.write(`
|
|
277
|
-
socket.write(`
|
|
288
|
+
socket.write(` \x1b[32mhelp, ?\x1b[0m - Mostrar esta ayuda\n`);
|
|
289
|
+
socket.write(` \x1b[32mquit\x1b[0m - Cerrar conexión\n\n`);
|
|
278
290
|
|
|
279
291
|
socket.write(`> `);
|
|
280
292
|
|
|
@@ -282,16 +294,59 @@ class AdminExtension {
|
|
|
282
294
|
const input = data.toString();
|
|
283
295
|
// Dividir la entrada en líneas y procesar cada una
|
|
284
296
|
const lines = input.split('\n').filter(line => line.trim() !== '');
|
|
285
|
-
|
|
297
|
+
|
|
286
298
|
for (const line of lines) {
|
|
299
|
+
// Verificar si hay un proceso interactivo activo para este socket
|
|
300
|
+
const controllerGenModule = this.modules.get('controllergeneratormodule');
|
|
301
|
+
if (controllerGenModule && controllerGenModule.instance && controllerGenModule.instance.currentProcess) {
|
|
302
|
+
const sessionId = controllerGenModule.instance.getSessionId(socket);
|
|
303
|
+
if (controllerGenModule.instance.currentProcess.has(sessionId)) {
|
|
304
|
+
// Si hay un proceso interactivo activo, delegar el manejo de la entrada
|
|
305
|
+
controllerGenModule.instance.processInput(socket, line.trim());
|
|
306
|
+
continue; // Saltar el procesamiento normal
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Verificar si hay un proceso interactivo activo para el módulo de gestión de rutas
|
|
311
|
+
const routeManagerModule = this.modules.get('routemanagermodule');
|
|
312
|
+
if (routeManagerModule && routeManagerModule.instance && routeManagerModule.instance.currentProcess) {
|
|
313
|
+
const sessionId = routeManagerModule.instance.getSessionId(socket);
|
|
314
|
+
if (routeManagerModule.instance.currentProcess.has(sessionId)) {
|
|
315
|
+
// Si hay un proceso interactivo activo, delegar el manejo de la entrada
|
|
316
|
+
routeManagerModule.instance.processInput(socket, line.trim());
|
|
317
|
+
continue; // Saltar el procesamiento normal
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Verificar si hay un proceso interactivo activo para el módulo de WAF
|
|
322
|
+
const wafModule = this.modules.get('wafmodule');
|
|
323
|
+
if (wafModule && wafModule.instance && wafModule.instance.currentProcess) {
|
|
324
|
+
const sessionId = wafModule.instance.getSessionId(socket);
|
|
325
|
+
if (wafModule.instance.currentProcess.has(sessionId)) {
|
|
326
|
+
// Si hay un proceso interactivo activo, delegar el manejo de la entrada
|
|
327
|
+
wafModule.instance.processInput(socket, line.trim());
|
|
328
|
+
continue; // Saltar el procesamiento normal
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Verificar si hay un proceso interactivo activo para el módulo de gestión de colas
|
|
333
|
+
const queueModule = this.modules.get('queuemanagementmodule');
|
|
334
|
+
if (queueModule && queueModule.instance && queueModule.instance.inputState &&
|
|
335
|
+
queueModule.instance.inputState.has(socket)) {
|
|
336
|
+
// Si hay un proceso interactivo activo, delegar el manejo de la entrada
|
|
337
|
+
queueModule.instance.processQueueAction(socket, queueModule.instance.inputState.get(socket).action, line.trim());
|
|
338
|
+
continue; // Saltar el procesamiento normal
|
|
339
|
+
}
|
|
340
|
+
|
|
287
341
|
const command = line.trim().toLowerCase();
|
|
288
342
|
console.log(`DEBUG: Comando recibido: "${command}"`); // Mensaje de depuración
|
|
289
|
-
|
|
343
|
+
|
|
290
344
|
// Verificar si es un comando de sistema
|
|
291
|
-
if (['help', 'quit', 'exit'].includes(command)) {
|
|
345
|
+
if (['help', 'quit', 'exit', '?'].includes(command)) {
|
|
292
346
|
console.log(`DEBUG: Comando de sistema encontrado: ${command}`); // Mensaje de depuración
|
|
293
347
|
switch (command) {
|
|
294
348
|
case 'help':
|
|
349
|
+
case '?':
|
|
295
350
|
this.sendHelp(socket);
|
|
296
351
|
break;
|
|
297
352
|
case 'quit':
|
|
@@ -309,7 +364,7 @@ class AdminExtension {
|
|
|
309
364
|
let handled = false;
|
|
310
365
|
console.log(`DEBUG: Buscando módulo para el comando "${command}"`); // Mensaje de depuración
|
|
311
366
|
console.log(`DEBUG: Módulos disponibles:`, Array.from(this.modules.keys())); // Mensaje de depuración
|
|
312
|
-
|
|
367
|
+
|
|
313
368
|
for (const [moduleName, module] of this.modules) {
|
|
314
369
|
console.log(`DEBUG: Revisando módulo "${moduleName}", comandos:`, module.commands); // Mensaje de depuración
|
|
315
370
|
if (module.commands.includes(command)) {
|
|
@@ -403,11 +458,11 @@ class AdminExtension {
|
|
|
403
458
|
socket.write(`Módulos disponibles:\n`);
|
|
404
459
|
for (const [name, module] of this.modules) {
|
|
405
460
|
socket.write(` ${name}: ${module.description}\n`);
|
|
406
|
-
socket.write(` Comandos: ${module.commands.join(', ')}\n`);
|
|
461
|
+
socket.write(` Comandos: \x1b[32m${module.commands.join(', ')}\x1b[0m\n`);
|
|
407
462
|
}
|
|
408
463
|
socket.write(`\nComandos generales:\n`);
|
|
409
|
-
socket.write(`
|
|
410
|
-
socket.write(`
|
|
464
|
+
socket.write(` \x1b[32mhelp, ?\x1b[0m - Mostrar esta ayuda\n`);
|
|
465
|
+
socket.write(` \x1b[32mquit\x1b[0m - Cerrar conexión\n\n`);
|
|
411
466
|
socket.write(`> `);
|
|
412
467
|
}
|
|
413
468
|
|
|
@@ -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;
|