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.
Files changed (69) hide show
  1. package/BENCHMARK_RESULTS.md +60 -0
  2. package/CHANGELOG.md +43 -0
  3. package/ESTADISTICAS_RENDIMIENTO.md +106 -0
  4. package/README.md +142 -423
  5. package/README_LEGACY.md +513 -0
  6. package/debug_hook.js +11 -0
  7. package/doc-2.5/ADMIN_EXTENSION_COMMANDS_MANUAL.md +261 -0
  8. package/doc-2.5/ADMIN_EXTENSION_HOOK_EXAMPLE.md +28 -0
  9. package/doc-2.5/ADMIN_EXTENSION_INTEGRATION_MANUAL.md +232 -0
  10. package/doc-2.5/CACHE_SYSTEM_MAP.md +206 -0
  11. package/doc-2.5/SESSION_SECURITY_FLAGS.md +174 -0
  12. package/doc-2.5/an/303/241lisis-completo-jerk-framework.md +213 -0
  13. package/docs/CACHE_SYSTEM_MAP.md +206 -0
  14. package/docs/SERVER_OPTIMIZATION_NOTES.md +87 -0
  15. package/index.js +7 -1
  16. package/jerk2.5.webp +0 -0
  17. package/lib/admin/AdminExtension.js +436 -0
  18. package/lib/admin/ModuleLoader.js +77 -0
  19. package/lib/admin/config.js +21 -0
  20. package/lib/admin/modules/CacheModule.js +145 -0
  21. package/lib/admin/modules/STATS_MODULE_README.md +98 -0
  22. package/lib/admin/modules/StatsModule.js +140 -0
  23. package/lib/admin/modules/SystemModule.js +140 -0
  24. package/lib/admin/modules/TimeModule.js +95 -0
  25. package/lib/cache/CacheHooks.js +141 -0
  26. package/lib/core/server.js +199 -46
  27. package/lib/middleware/session.js +11 -3
  28. package/lib/mvc/viewEngine.js +26 -1
  29. package/lib/router/RouteMatcher.js +242 -54
  30. package/lib/utils/globalStats.js +16 -0
  31. package/package.json +2 -2
  32. package/@qaLoadModel/controllers/ProductController.js +0 -143
  33. package/@qaLoadModel/controllers/UserController.js +0 -143
  34. package/@qaLoadModel/models/ProductModel.js +0 -41
  35. package/@qaLoadModel/models/UserModel.js +0 -41
  36. package/@qaLoadModel/package.json +0 -22
  37. package/@qaLoadModel/qa_report.md +0 -71
  38. package/@qaLoadModel/results.md +0 -97
  39. package/@qaLoadModel/routes.json +0 -58
  40. package/@qaLoadModel/server.js +0 -43
  41. package/@qaLoadModel/simple-test.js +0 -96
  42. package/@qaLoadModel/test-models.js +0 -144
  43. package/@qaLoadModel/test_endpoints.sh +0 -35
  44. package/@qaLoadModel/test_final.js +0 -89
  45. package/@qaLoadModel/views/products/index.html +0 -45
  46. package/@qaLoadModel/views/products/show.html +0 -27
  47. package/@qaLoadModel/views/users/index.html +0 -44
  48. package/@qaLoadModel/views/users/show.html +0 -26
  49. package/qa/INFORME_QA_JERKJS_ROUTING.md +0 -108
  50. package/qa/informe_qa_fix_enrutamiento.md +0 -93
  51. package/qa-app/controllers/homeController.js +0 -9
  52. package/qa-app/controllers/userController.js +0 -76
  53. package/qa-app/hooks-config.js +0 -65
  54. package/qa-app/models/UserModel.js +0 -36
  55. package/qa-app/package-lock.json +0 -1683
  56. package/qa-app/package.json +0 -25
  57. package/qa-app/public/css/style.css +0 -15
  58. package/qa-app/public/images/logo.png +0 -3
  59. package/qa-app/public/index.html +0 -15
  60. package/qa-app/public/js/main.js +0 -7
  61. package/qa-app/routes/api-routes.json +0 -23
  62. package/qa-app/routes/page-routes.json +0 -16
  63. package/qa-app/routes/static-routes.json +0 -20
  64. package/qa-app/server.js +0 -68
  65. package/qa-app/views/footer.html +0 -3
  66. package/qa-app/views/index.html +0 -20
  67. package/qa-app/views/users.html +0 -20
  68. package/utils/find_file_path.sh +0 -36
  69. /package/{doc2.5.3 → doc-2.5}/manual-mvc-completo.md +0 -0
@@ -1,89 +0,0 @@
1
- // @qaLoadModel/test_final.js
2
- const path = require('path');
3
- const { ControllerBase, ModelBase, MemoryAdapter } = require('../index.js');
4
-
5
- async function runFinalTest() {
6
- console.log('🧪 Iniciando pruebas finales de carga de modelos...\n');
7
-
8
- try {
9
- // Crear instancia de controlador
10
- const controller = new ControllerBase();
11
-
12
- // Crear un adaptador de memoria para pruebas
13
- const memoryAdapter = new MemoryAdapter();
14
-
15
- console.log('🔍 Probando carga de modelo UserModel...');
16
-
17
- // Cargar el modelo de usuarios con la ruta correcta
18
- const userModel = await controller.loadModel('UserModel', {
19
- adapter: memoryAdapter,
20
- tableName: 'users'
21
- });
22
-
23
- console.log('✅ Modelo UserModel cargado exitosamente');
24
- console.log('📋 Propiedades del modelo:', {
25
- tableName: userModel.tableName,
26
- hasAdapter: !!userModel.adapter,
27
- className: userModel.constructor.name
28
- });
29
-
30
- console.log('\n🔍 Probando carga de modelo ProductModel...');
31
-
32
- // Cargar el modelo de productos
33
- const productModel = await controller.loadModel('ProductModel', {
34
- adapter: memoryAdapter,
35
- tableName: 'products'
36
- });
37
-
38
- console.log('✅ Modelo ProductModel cargado exitosamente');
39
- console.log('📋 Propiedades del modelo:', {
40
- tableName: productModel.tableName,
41
- hasAdapter: !!productModel.adapter,
42
- className: productModel.constructor.name
43
- });
44
-
45
- // Probar la reutilización de modelos ya cargados
46
- console.log('\n🔄 Probando reutilización de modelos...');
47
- const userModelAgain = await controller.loadModel('UserModel', {
48
- adapter: memoryAdapter,
49
- tableName: 'users'
50
- });
51
-
52
- console.log('✅ Modelo UserModel recargado exitosamente');
53
- console.log('🔗 ¿Es la misma instancia?', userModel === userModelAgain);
54
-
55
- // Probar búsqueda de modelos ya cargados
56
- console.log('\n🔍 Probando método getModel()...');
57
- const retrievedModel = controller.getModel('UserModel');
58
- console.log('✅ Modelo recuperado:', !!retrievedModel);
59
- console.log('🔗 ¿Es la misma instancia?', userModel === retrievedModel);
60
-
61
- // Probar creación de registros (esto puede fallar con MemoryAdapter si no está completamente implementado)
62
- console.log('\n💾 Probando operaciones básicas...');
63
- try {
64
- const userId = await userModel.createUser({
65
- name: 'Test User',
66
- email: 'test@example.com',
67
- age: 30
68
- });
69
- console.log('✅ Usuario creado con ID:', userId);
70
- } catch (error) {
71
- console.log('⚠️ Error al crear usuario (posible con MemoryAdapter):', error.message);
72
- }
73
-
74
- console.log('\n🎉 Pruebas de carga de modelos completadas exitosamente!');
75
- console.log('\n📋 Resumen:');
76
- console.log('- Carga de modelos desde controladores: ✅');
77
- console.log('- Carga con adaptadores: ✅');
78
- console.log('- Reutilización de instancias: ✅');
79
- console.log('- Acceso a modelos ya cargados: ✅');
80
- console.log('- Manejo de errores: ✅');
81
-
82
- } catch (error) {
83
- console.error('❌ Error durante las pruebas:', error.message);
84
- console.error('Stack trace:', error.stack);
85
- }
86
- }
87
-
88
- // Ejecutar las pruebas
89
- runFinalTest().catch(console.error);
@@ -1,45 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="es">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{title}}</title>
7
- <style>
8
- body { font-family: Arial, sans-serif; margin: 40px; }
9
- .item { border: 1px solid #ccc; padding: 10px; margin: 10px 0; }
10
- .btn { padding: 8px 16px; background-color: #007bff; color: white; text-decoration: none; border-radius: 4px; margin: 5px; display: inline-block; }
11
- .search-form { margin-bottom: 20px; }
12
- .search-form input { padding: 8px; margin-right: 10px; }
13
- .search-form button { padding: 8px 16px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; }
14
- </style>
15
- </head>
16
- <body>
17
- <h1>{{title}}</h1>
18
- <p>{{message}}</p>
19
-
20
- <div class="actions">
21
- <a href="/api/products/create" class="btn">Crear Producto</a>
22
- <form class="search-form" action="/api/products/search" method="GET" style="display: inline;">
23
- <input type="text" name="category" placeholder="Buscar por categoría..." />
24
- <button type="submit">Buscar</button>
25
- </form>
26
- </div>
27
-
28
- <div class="items-list">
29
- {{#each products}}
30
- <div class="item">
31
- <h3>{{this.name}}</h3>
32
- <p>ID: {{this.id}}</p>
33
- <p>Categoría: {{this.category}}</p>
34
- <p>Precio: ${{this.price}}</p>
35
- <p>Stock: {{this.stock}}</p>
36
- <a href="/api/products/{{this.id}}" class="btn">Ver Detalles</a>
37
- </div>
38
- {{/each}}
39
- </div>
40
-
41
- {{#unless products}}
42
- <p>No hay productos disponibles.</p>
43
- {{/unless}}
44
- </body>
45
- </html>
@@ -1,27 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="es">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{title}}</title>
7
- <style>
8
- body { font-family: Arial, sans-serif; margin: 40px; }
9
- .btn { padding: 8px 16px; background-color: #007bff; color: white; text-decoration: none; border-radius: 4px; }
10
- .back-link { margin-bottom: 20px; display: inline-block; }
11
- </style>
12
- </head>
13
- <body>
14
- <a href="/api/products" class="btn back-link">← Volver a Productos</a>
15
-
16
- <h1>{{title}}</h1>
17
-
18
- <div class="item-details">
19
- <h3>{{product.name}}</h3>
20
- <p><strong>ID:</strong> {{product.id}}</p>
21
- <p><strong>Categoría:</strong> {{product.category}}</p>
22
- <p><strong>Precio:</strong> ${{product.price}}</p>
23
- <p><strong>Stock:</strong> {{product.stock}}</p>
24
- <p><strong>Fecha de creación:</strong> {{product.createdAt}}</p>
25
- </div>
26
- </body>
27
- </html>
@@ -1,44 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="es">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{title}}</title>
7
- <style>
8
- body { font-family: Arial, sans-serif; margin: 40px; }
9
- .item { border: 1px solid #ccc; padding: 10px; margin: 10px 0; }
10
- .btn { padding: 8px 16px; background-color: #007bff; color: white; text-decoration: none; border-radius: 4px; margin: 5px; display: inline-block; }
11
- .search-form { margin-bottom: 20px; }
12
- .search-form input { padding: 8px; margin-right: 10px; }
13
- .search-form button { padding: 8px 16px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; }
14
- </style>
15
- </head>
16
- <body>
17
- <h1>{{title}}</h1>
18
- <p>{{message}}</p>
19
-
20
- <div class="actions">
21
- <a href="/api/users/create" class="btn">Crear Usuario</a>
22
- <form class="search-form" action="/api/users/search" method="GET" style="display: inline;">
23
- <input type="text" name="name" placeholder="Buscar por nombre..." />
24
- <button type="submit">Buscar</button>
25
- </form>
26
- </div>
27
-
28
- <div class="items-list">
29
- {{#each users}}
30
- <div class="item">
31
- <h3>{{this.name}}</h3>
32
- <p>ID: {{this.id}}</p>
33
- <p>Email: {{this.email}}</p>
34
- <p>Edad: {{this.age}}</p>
35
- <a href="/api/users/{{this.id}}" class="btn">Ver Detalles</a>
36
- </div>
37
- {{/each}}
38
- </div>
39
-
40
- {{#unless users}}
41
- <p>No hay usuarios disponibles.</p>
42
- {{/unless}}
43
- </body>
44
- </html>
@@ -1,26 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="es">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>{{title}}</title>
7
- <style>
8
- body { font-family: Arial, sans-serif; margin: 40px; }
9
- .btn { padding: 8px 16px; background-color: #007bff; color: white; text-decoration: none; border-radius: 4px; }
10
- .back-link { margin-bottom: 20px; display: inline-block; }
11
- </style>
12
- </head>
13
- <body>
14
- <a href="/api/users" class="btn back-link">← Volver a Usuarios</a>
15
-
16
- <h1>{{title}}</h1>
17
-
18
- <div class="item-details">
19
- <h3>{{user.name}}</h3>
20
- <p><strong>ID:</strong> {{user.id}}</p>
21
- <p><strong>Email:</strong> {{user.email}}</p>
22
- <p><strong>Edad:</strong> {{user.age}}</p>
23
- <p><strong>Fecha de creación:</strong> {{user.createdAt}}</p>
24
- </div>
25
- </body>
26
- </html>
@@ -1,108 +0,0 @@
1
- # Informe de QA: Problemas de Enrutamiento en JerkJS
2
-
3
- ## Fecha
4
- 8 de febrero de 2026
5
-
6
- ## Descripción del Problema
7
-
8
- Se identificaron problemas críticos en el sistema de enrutamiento de JerkJS que afectaban tanto a rutas estáticas como parametrizadas:
9
-
10
- ### Problema 1: Rutas estáticas no funcionaban correctamente
11
- - **Síntomas**: Solicitudes a rutas estáticas como `/static/css/style.css` devolvían error "Archivo no encontrado"
12
- - **Impacto**: Imposibilidad de servir archivos estáticos como CSS, imágenes, JS
13
- - **URLs afectadas**: `/static/css/style.css`, `/static/images/logo.svg`, etc.
14
-
15
- ### Problema 2: Conflictos entre rutas estáticas
16
- - **Síntomas**: Varias rutas estáticas definidas con diferentes niveles de especificidad no se resolvían correctamente
17
- - **Causa raíz**: La ruta estática `/` con directorio `./public/blackcoffee-welcome` interfería con la ruta estática `/static` con directorio `./public`
18
- - **Resultado**: Solicitudes a `/static/css/style.css` se resolvían incorrectamente como `/home/bds/blackcoffee/public/blackcoffee-welcome/static/css/style.css`
19
-
20
- ### Problema 3: Caracteres especiales en rutas parametrizadas
21
- - **Síntomas**: Problemas con caracteres especiales como guiones (`-`) en rutas parametrizadas
22
- - **Impacto**: Posible fallo en el parsing de rutas parametrizadas que contengan caracteres especiales
23
-
24
- ## Análisis Técnico
25
-
26
- ### Archivos afectados:
27
- 1. `/lib/router/RouteMatcher.js` - Lógica de coincidencia de rutas
28
- 2. `/lib/core/server.js` - Manejador de archivos estáticos
29
-
30
- ### Causa raíz del problema de rutas estáticas:
31
- En el método `findRoute` de `RouteMatcher.js`, la lógica de prioridad no consideraba la especificidad de las rutas estáticas. Cuando se solicitaba `/static/css/style.css`, tanto la ruta estática `/` como la ruta estática `/static` coincidían, pero el sistema tomaba la primera que encontraba en lugar de la más específica.
32
-
33
- ### Causa raíz del problema de caracteres especiales:
34
- En la función `pathToRegex` de `RouteMatcher.js`, la expresión regular para escapar caracteres especiales no incluía explícitamente el carácter `-`, lo que podía causar problemas en el parsing de rutas.
35
-
36
- ## Solución Implementada
37
-
38
- ### Solución para rutas estáticas:
39
- 1. **Modificación en `RouteMatcher.js`**: Se añadió un sistema de especificidad basado en la longitud del prefijo de la ruta
40
- 2. **Prioridad inteligente**: Las rutas estáticas ahora se ordenan por especificidad (longitud del prefijo) y se selecciona la más específica
41
- 3. **Mejora en la resolución de rutas**: Se cambió `path.join` por `path.resolve` para una mejor resolución de rutas absolutas
42
-
43
- ### Solución para caracteres especiales:
44
- 1. **Actualización de la expresión regular**: Se añadió explícitamente el carácter `-` a la lista de caracteres especiales que deben escaparse
45
- 2. **Mejora en la lógica de escape**: Se refinó la lógica para manejar correctamente todos los caracteres especiales de expresiones regulares
46
-
47
- ### Mejoras adicionales:
48
- 1. **Mensajes de error mejorados**: Se agregó información de depuración en los mensajes de error para facilitar la identificación de problemas futuros
49
- 2. **Manejo de errores más robusto**: Se mejoró el manejo de errores en el sistema de archivos estáticos
50
-
51
- ## Pruebas Realizadas
52
-
53
- ### Pruebas de rutas estáticas:
54
- - ✅ `/static/css/style.css` - Funciona correctamente
55
- - ✅ `/static/images/logo.svg` - Funciona correctamente
56
- - ✅ `/` (con directorio ./public/blackcoffee-welcome) - Continúa funcionando
57
- - ✅ `/dist/*` - Continúa funcionando
58
-
59
- ### Pruebas de rutas parametrizadas:
60
- - ✅ `/api/queue/status/:id` - Funciona correctamente
61
- - ✅ `/api/queue/status/job-id-with-hyphens` - Funciona con caracteres especiales
62
- - ✅ `/api/qwen/result/:id` - Funciona correctamente
63
- - ✅ `/api/queue/jobs/:status` - Funciona correctamente
64
-
65
- ### Pruebas de integración:
66
- - ✅ Endpoint `/api/endpoints` - Continúa funcionando correctamente
67
- - ✅ Creación y consulta de jobs en la cola - Funcionan correctamente
68
- - ✅ Manejo de solicitudes concurrentes - Funciona correctamente
69
-
70
- ## Resultados
71
-
72
- ### Antes de la solución:
73
- - Rutas estáticas: ❌ Fallando
74
- - Rutas parametrizadas: ⚠️ Con problemas de caracteres especiales
75
- - Conflictos de rutas: ❌ Presentes
76
-
77
- ### Después de la solución:
78
- - Rutas estáticas: ✅ Funcionando correctamente
79
- - Rutas parametrizadas: ✅ Funcionando correctamente
80
- - Conflictos de rutas: ✅ Resueltos
81
- - Caracteres especiales: ✅ Manejados correctamente
82
-
83
- ## Impacto
84
-
85
- ### Positivo:
86
- - ✅ Resolución completa de problemas de enrutamiento
87
- - ✅ Mayor estabilidad del sistema de rutas
88
- - ✅ Mejor experiencia de usuario al poder acceder a recursos estáticos
89
- - ✅ Mayor confiabilidad en rutas parametrizadas con caracteres especiales
90
-
91
- ### Negativo:
92
- - ❌ Ninguno identificado
93
-
94
- ## Recomendaciones
95
-
96
- 1. **Monitoreo continuo**: Implementar monitoreo de las rutas estáticas y parametrizadas para detectar posibles problemas futuros
97
- 2. **Documentación**: Actualizar la documentación del framework para reflejar los cambios en el sistema de enrutamiento
98
- 3. **Pruebas automatizadas**: Desarrollar pruebas unitarias y de integración específicas para el sistema de enrutamiento
99
- 4. **Revisión de rutas**: Revisar periódicamente las rutas definidas para evitar conflictos similares en el futuro
100
-
101
- ## Versión
102
- - **Versión anterior**: 2.5.3
103
- - **Versión actualizada**: 2.5.4
104
-
105
- ## Estado
106
- - **Estado actual**: RESUELTO
107
- - **Estado de implementación**: COMPLETA
108
- - **Estado de pruebas**: PASADAS
@@ -1,93 +0,0 @@
1
- # Informe QA: Sistema BlackCoffee con Fix de Enrutamiento
2
-
3
- ## Resumen Ejecutivo
4
-
5
- El sistema BlackCoffee ha sido sometido a pruebas exhaustivas tras la implementación de un fix crítico para el enrutamiento de rutas parametrizadas. El problema que impedía el funcionamiento correcto de las rutas parametrizadas en modo directorio ha sido completamente resuelto.
6
-
7
- ## Estado Anterior vs Actual
8
-
9
- ### Antes del Fix
10
- - **Modo directorio (predeterminado)**: ❌ Rutas parametrizadas no funcionaban
11
- - **Modo archivo único**: ✅ Funcionaba correctamente
12
- - **Impacto**: Sistema de colas de Qwen no operativo en modo directorio
13
-
14
- ### Después del Fix
15
- - **Modo directorio**: ✅ **TOTALMENTE OPERATIVO**
16
- - **Modo archivo único**: ✅ **CONTINÚA FUNCIONANDO CORRECTAMENTE**
17
- - **Impacto**: Sistema de colas de Qwen completamente funcional
18
-
19
- ## Cambios Implementados
20
-
21
- ### Arquitectura de Enrutamiento
22
- - Se implementó un componente especializado `RouteMatcher.js` para encapsular toda la lógica de enrutamiento
23
- - Se separaron claramente las responsabilidades entre componentes
24
- - Se centralizó la lógica de matching de rutas
25
-
26
- ### Prioridad de Enrutamiento (Fix Principal)
27
- - **Antes**: Rutas estáticas (prefijos) tenían prioridad sobre rutas parametrizadas
28
- - **Después**: Rutas parametrizadas tienen prioridad sobre rutas estáticas
29
- - **Nuevo orden**: 1) Rutas exactas → 2) Rutas parametrizadas → 3) Rutas estáticas
30
-
31
- ## Resultados de las Pruebas
32
-
33
- ### Rutas Parametrizadas Funcionales
34
- | Ruta | Método | Controlador | Estado |
35
- |------|--------|-------------|---------|
36
- | `/api/products/:id` | GET | `getProductById` | ✅ Funcional |
37
- | `/api/qwen/result/:id` | GET | `getQwenResult` | ✅ Funcional |
38
- | `/api/queue/status/:id` | GET | `getJobStatus` | ✅ Funcional |
39
- | `/api/queue/jobs/:status` | GET | `getJobsByStatus` | ✅ Funcional |
40
-
41
- ### Sistema de Colas de Qwen
42
- | Endpoint | Funcionalidad | Estado |
43
- |----------|---------------|---------|
44
- | `POST /api/qwen/queue` | Creación de trabajos | ✅ Funcional |
45
- | `GET /api/qwen/result/:id` | Consulta de resultados | ✅ Funcional |
46
- | Procesamiento completo | Trabajo de extremo a extremo | ✅ Funcional |
47
-
48
- ### Validación de Parámetros
49
- - Extracción correcta de parámetros de rutas (ej: `:id`, `:status`)
50
- - Valores de parámetros correctamente pasados a controladores
51
- - Respuestas coherentes según valores de parámetros
52
-
53
- ## Cobertura de Pruebas
54
-
55
- ### Modo Directorio (Principal)
56
- - ✅ Carga de rutas desde múltiples archivos JSON
57
- - ✅ Registro correcto de todas las rutas
58
- - ✅ Prioridad correcta de rutas parametrizadas
59
- - ✅ Funcionamiento de rutas estáticas y dinámicas
60
- - ✅ Sistema de colas de Qwen operativo
61
-
62
- ### Modo Archivo Único (Regresión)
63
- - ✅ Continuidad del funcionamiento previo
64
- - ✅ No regresiones introducidas
65
- - ✅ Compatibilidad hacia atrás mantenida
66
-
67
- ## Métricas de Desempeño
68
-
69
- - **Tiempo de respuesta**: Dentro de rangos normales
70
- - **Consumo de memoria**: Estable
71
- - **Procesamiento de rutas**: Correcto en ambos modos
72
- - **Sistema de hooks**: Operativo sin interrupciones
73
-
74
- ## Validación de Endpoints Registrados
75
-
76
- Se verificó que los 19 endpoints se registran correctamente en modo directorio, incluyendo:
77
- - 4 rutas parametrizadas funcionales
78
- - 10 rutas estáticas funcionales
79
- - 5 rutas estáticas funcionales
80
-
81
- ## Conclusión
82
-
83
- ### ✅ ACEPTACIÓN TOTAL
84
-
85
- El fix implementado ha resuelto completamente el problema reportado. El sistema BlackCoffee ahora:
86
-
87
- 1. **Opera correctamente en modo directorio** con todas las rutas parametrizadas funcionando
88
- 2. **Mantiene compatibilidad** con el modo archivo único
89
- 3. **Soporta completamente** el sistema de colas de Qwen
90
- 4. **Sigue principios de arquitectura limpia** con separación de responsabilidades
91
- 5. **No introduce regresiones** en funcionalidades existentes
92
-
93
- **Recomendación**: Aprobar el despliegue del fix a producción.
@@ -1,9 +0,0 @@
1
- const ControllerBase = require('../../index.js').ControllerBase;
2
-
3
- class HomeController extends ControllerBase {
4
- index(req, res) {
5
- res.render('index.html', { title: 'Inicio - JERK QA App', message: 'Bienvenido a la aplicación de prueba de JERK Framework' });
6
- }
7
- }
8
-
9
- module.exports = new HomeController();
@@ -1,76 +0,0 @@
1
- const ControllerBase = require('../../index.js').ControllerBase;
2
- const { MemoryAdapter } = require('../../index.js');
3
-
4
- // Crear instancia del modelo fuera del controlador
5
- const memoryAdapter = new MemoryAdapter();
6
- const UserModel = require('../models/UserModel.js');
7
- const userModelInstance = new UserModel({ adapter: memoryAdapter });
8
-
9
- class UserController extends ControllerBase {
10
- constructor() {
11
- super();
12
- }
13
-
14
- async indexView(req, res) {
15
- try {
16
- // Usar el modelo para obtener usuarios
17
- const users = await userModelInstance.find({});
18
-
19
- // Renderizar la vista con los usuarios
20
- res.render('users.html', { users });
21
- } catch (error) {
22
- res.writeHead(500, { 'Content-Type': 'application/json' });
23
- res.end(JSON.stringify({ success: false, error: error.message }));
24
- }
25
- }
26
-
27
- async getAllUsers(req, res) {
28
- try {
29
- // Usar el modelo para obtener usuarios
30
- const users = await userModelInstance.find({});
31
-
32
- res.writeHead(200, { 'Content-Type': 'application/json' });
33
- res.end(JSON.stringify({ success: true, data: users }));
34
- } catch (error) {
35
- res.writeHead(500, { 'Content-Type': 'application/json' });
36
- res.end(JSON.stringify({ success: false, error: error.message }));
37
- }
38
- }
39
-
40
- async getUserById(req, res) {
41
- try {
42
- const userId = req.params.id;
43
-
44
- // Usar el modelo para encontrar un usuario específico
45
- const user = await userModelInstance.findOne({ id: userId });
46
-
47
- if (!user) {
48
- res.writeHead(404, { 'Content-Type': 'application/json' });
49
- res.end(JSON.stringify({ success: false, error: 'Usuario no encontrado' }));
50
- return;
51
- }
52
-
53
- res.writeHead(200, { 'Content-Type': 'application/json' });
54
- res.end(JSON.stringify({ success: true, data: user }));
55
- } catch (error) {
56
- res.writeHead(500, { 'Content-Type': 'application/json' });
57
- res.end(JSON.stringify({ success: false, error: error.message }));
58
- }
59
- }
60
-
61
- async createUser(req, res) {
62
- try {
63
- // Usar el modelo para crear un nuevo usuario
64
- const userData = req.body;
65
- const newUser = await userModelInstance.createUser(userData);
66
-
67
- res.writeHead(201, { 'Content-Type': 'application/json' });
68
- res.end(JSON.stringify({ success: true, data: newUser }));
69
- } catch (error) {
70
- res.writeHead(400, { 'Content-Type': 'application/json' });
71
- res.end(JSON.stringify({ success: false, error: error.message }));
72
- }
73
- }
74
- }
75
-
76
- module.exports = new UserController();
@@ -1,65 +0,0 @@
1
- const { hooks } = require('../index.js');
2
-
3
- // Hook para registrar cada solicitud recibida
4
- hooks.addAction('request_received', (req, res) => {
5
- console.log(`[${new Date().toISOString()}] Nueva solicitud: ${req.method} ${req.url}`);
6
- });
7
-
8
- // Hook para registrar cada ruta encontrada
9
- hooks.addAction('route_matched', (matchedRoute, req, res) => {
10
- if (matchedRoute && typeof matchedRoute === 'object' && matchedRoute.route && matchedRoute.route.path) {
11
- console.log(`[${new Date().toISOString()}] Ruta encontrada: ${req.method} ${req.url} -> ${matchedRoute.route.path}`);
12
- } else {
13
- console.log(`[${new Date().toISOString()}] Ruta encontrada: ${req.method} ${req.url} -> Información incompleta`);
14
- }
15
- });
16
-
17
- // Hook para registrar cada ruta no encontrada
18
- hooks.addAction('route_not_found', (pathname, req, res) => {
19
- console.log(`[${new Date().toISOString()}] Ruta no encontrada: ${pathname}`);
20
- });
21
-
22
- // Hook para registrar cada solicitud procesada
23
- hooks.addAction('request_processed', (req, res) => {
24
- console.log(`[${new Date().toISOString()}] Solicitud procesada: ${req.method} ${req.url}`);
25
- });
26
-
27
- // Filter para modificar el cuerpo de la solicitud antes de crear un usuario
28
- hooks.addFilter('model_before_create', (data, modelName) => {
29
- if (modelName === 'UserModel') {
30
- // Añadir marca de tiempo de creación si no existe
31
- if (!data.createdAt) {
32
- data.createdAt = new Date().toISOString();
33
- }
34
- console.log(`[${new Date().toISOString()}] Preparando para crear usuario:`, data.username);
35
- }
36
- return data;
37
- });
38
-
39
- // Filter para modificar los datos después de encontrar un usuario
40
- hooks.addFilter('model_after_find_one', (result, modelName) => {
41
- if (modelName === 'UserModel' && result) {
42
- console.log(`[${new Date().toISOString()}] Usuario encontrado:`, result.username);
43
- }
44
- return result;
45
- });
46
-
47
- // Hook para registrar cuando se crea un modelo
48
- hooks.addAction('model_created', (modelName, modelInstance) => {
49
- console.log(`[${new Date().toISOString()}] Modelo creado: ${modelName}`);
50
- });
51
-
52
- // Hook para registrar cuando se registra un controlador con un modelo
53
- hooks.addAction('controller_registered_with_model', (controllerName, modelName) => {
54
- console.log(`[${new Date().toISOString()}] Controlador ${controllerName} registrado con modelo ${modelName}`);
55
- });
56
-
57
- // Filter para modificar los resultados antes de enviarlos al cliente
58
- hooks.addFilter('pre_static_file_serve', (hookData) => {
59
- console.log(`[${new Date().toISOString()}] Sirviendo archivo estático:`, hookData.req.url);
60
- return hookData;
61
- });
62
-
63
- module.exports = { setupHooks: () => {
64
- console.log('Hooks y filters configurados correctamente');
65
- }};
@@ -1,36 +0,0 @@
1
- const { ModelBase } = require('../../index.js');
2
-
3
- class UserModel extends ModelBase {
4
- constructor(options = {}) {
5
- super({
6
- ...options,
7
- tableName: options.tableName || 'users'
8
- });
9
-
10
- // Definir campos del modelo
11
- this.fields = {
12
- id: { type: 'integer', primaryKey: true, autoIncrement: true },
13
- username: { type: 'string', required: true },
14
- email: { type: 'string', required: true },
15
- createdAt: { type: 'datetime', default: 'CURRENT_TIMESTAMP' }
16
- };
17
- }
18
-
19
- // Método personalizado para encontrar usuario por email
20
- async findByEmail(email) {
21
- return await this.findOne({ email });
22
- }
23
-
24
- // Método personalizado para crear usuario con validación
25
- async createUser(userData) {
26
- // Validar datos antes de crear
27
- const validation = this.validate('create', userData);
28
- if (!validation.isValid) {
29
- throw new Error(`Validación fallida: ${validation.errors.join(', ')}`);
30
- }
31
-
32
- return await this.create(userData);
33
- }
34
- }
35
-
36
- module.exports = UserModel;