blackcoffee2 2.1.0

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 (170) hide show
  1. package/CHANGELOG.md +664 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +25 -0
  4. package/README.md +246 -0
  5. package/apps.zip +0 -0
  6. package/bin/adminclient +105 -0
  7. package/bin/blackcoffee +133 -0
  8. package/cli/admin-users.js +282 -0
  9. package/cli/commands/app.js +561 -0
  10. package/cli/commands/config.js +182 -0
  11. package/cli/commands/db.js +257 -0
  12. package/cli/commands/server.js +200 -0
  13. package/config/applications.json +5 -0
  14. package/config/database.json +28 -0
  15. package/config/database.json.example +23 -0
  16. package/config/server.json +32 -0
  17. package/controllers/admin/AdminController.js +529 -0
  18. package/controllers/admin/AdminViewController.js +90 -0
  19. package/controllers/admin/AuthController.js +293 -0
  20. package/controllers/admin/DatabaseAdminController.js +218 -0
  21. package/core/SQLiteAdapter.js +333 -0
  22. package/core/appLoader.js +385 -0
  23. package/core/databasePoolManager.js +431 -0
  24. package/core/hotReload.js +363 -0
  25. package/data/ADMIN-README.md +145 -0
  26. package/data/CHANGELOG.md +48 -0
  27. package/data/GTK3-NODE-PROPOSALS.md +410 -0
  28. package/data/admin-db.js +150 -0
  29. package/data/admin-gui.js +452 -0
  30. package/data/blackcoffee_admin.db-shm +0 -0
  31. package/data/blackcoffee_admin.db-wal +0 -0
  32. package/data/migrations/001_create_admin_users.sql +33 -0
  33. package/docs/APP_HOOKS_HANDLER.md +432 -0
  34. package/docs/APP_HOOKS_REQUIREMENTS.md +588 -0
  35. package/docs/ARCHITECTURE.md +435 -0
  36. package/docs/CREAR_APP_Y_USAR_POOLS.md +1595 -0
  37. package/docs/EVENTS_APP_MANUAL.md +289 -0
  38. package/docs/INSITU_BINARY_UPLOAD_PROPOSAL.md +186 -0
  39. package/docs/INSITU_FIREWALL_EXCEPTION.md +187 -0
  40. package/docs/ROADMAP.md +242 -0
  41. package/docs/ROADMAP.md.backup +243 -0
  42. package/includes/404-hooks.js +423 -0
  43. package/includes/adminAuth.js +214 -0
  44. package/includes/adminExtension.js +53 -0
  45. package/includes/appHooks.js +302 -0
  46. package/includes/initAdminDb.js +115 -0
  47. package/includes/routeLoader.js +67 -0
  48. package/includes/sessions.js +223 -0
  49. package/issues/001-duplicate-module-loading.md +92 -0
  50. package/manuales/ADMIN_EXTENSION_COMMANDS_MANUAL.md +261 -0
  51. package/manuales/ADMIN_EXTENSION_HOOK_EXAMPLE.md +28 -0
  52. package/manuales/ADMIN_EXTENSION_INTEGRATION_MANUAL.md +232 -0
  53. package/manuales/CACHE_REGEX_COMMANDS.md +136 -0
  54. package/manuales/CACHE_SYSTEM_MAP.md +206 -0
  55. package/manuales/CREACION_DE_CONTROLADORES_INSITU.md +383 -0
  56. package/manuales/QUEUE_CLI_MODULE_MANUAL.md +289 -0
  57. package/manuales/QUEUE_SYSTEM_MANUAL.md +320 -0
  58. package/manuales/ROUTE_CACHE_MODULE_MANUAL.md +205 -0
  59. package/manuales/SESSION_MANAGER_GUIDE.md +529 -0
  60. package/manuales/SESSION_SECURITY_FLAGS.md +174 -0
  61. package/manuales/WAF_MODULE_MANUAL.md +229 -0
  62. package/manuales/after_route_handler_filter_example.md +116 -0
  63. package/manuales/after_route_handler_usage.md +130 -0
  64. package/manuales/an/303/241lisis-completo-insitu-framework.md +213 -0
  65. package/manuales/async_hooks_promises_guide.md +325 -0
  66. package/manuales/before_route_handler_filter_example.md +97 -0
  67. package/manuales/before_route_handler_usage.md +122 -0
  68. package/manuales/hooks_chaining_conditions_guide.md +261 -0
  69. package/manuales/hooks_filters_documentation.md +493 -0
  70. package/manuales/hooks_filters_documentation_en.md +493 -0
  71. package/manuales/hooks_vs_middlewares_comparison.md +87 -0
  72. package/manuales/manual-mvc-completo.md +934 -0
  73. package/manuales/modulos_administracion.md +89 -0
  74. package/manuales/router_execution_points.md +74 -0
  75. package/manuales/static_file_hooks_usage.md +222 -0
  76. package/models/AdminUserModel.js +132 -0
  77. package/package.json +45 -0
  78. package/programatically/PRoutes.js +89 -0
  79. package/programatically/initFlow.js +211 -0
  80. package/public/admin/css/db-pools.css +336 -0
  81. package/public/admin/css/styles.css +310 -0
  82. package/public/admin/database.html +312 -0
  83. package/public/admin/index.html +116 -0
  84. package/public/admin/js/app.js +470 -0
  85. package/public/admin/js/db-pools.js +253 -0
  86. package/public/admin/login.html +278 -0
  87. package/public/assets/css/styles.css +477 -0
  88. package/public/assets/js/main.js +89 -0
  89. package/public/index.html +136 -0
  90. package/public/templates/404.html +158 -0
  91. package/routes/admin-views.json +20 -0
  92. package/routes/admin.json +38 -0
  93. package/routes/auth.json +32 -0
  94. package/routes/static.json +18 -0
  95. package/server.js +299 -0
  96. package/test-aplicacion.con-logisession/BlackCoffee.js +226 -0
  97. package/test-aplicacion.con-logisession/SSL_SETUP.md +53 -0
  98. package/test-aplicacion.con-logisession/certs/ca-certificate.pem +32 -0
  99. package/test-aplicacion.con-logisession/certs/ca-private-key.pem +52 -0
  100. package/test-aplicacion.con-logisession/certs/certificate-2048.pem +22 -0
  101. package/test-aplicacion.con-logisession/certs/certificate.pem +32 -0
  102. package/test-aplicacion.con-logisession/certs/private-key-2048.pem +28 -0
  103. package/test-aplicacion.con-logisession/certs/private-key.pem +52 -0
  104. package/test-aplicacion.con-logisession/config/iaQueueSetup.js +84 -0
  105. package/test-aplicacion.con-logisession/config/qwen-rules.json +39 -0
  106. package/test-aplicacion.con-logisession/controllers/analyticsController.js +117 -0
  107. package/test-aplicacion.con-logisession/controllers/auth/AdminAuthController.js +142 -0
  108. package/test-aplicacion.con-logisession/controllers/auth/AuthController.js +439 -0
  109. package/test-aplicacion.con-logisession/controllers/auth/AuthViewController.js +223 -0
  110. package/test-aplicacion.con-logisession/controllers/endpointController.js +66 -0
  111. package/test-aplicacion.con-logisession/controllers/example.js +183 -0
  112. package/test-aplicacion.con-logisession/controllers/iaQueueController.js +367 -0
  113. package/test-aplicacion.con-logisession/controllers/queueController.js +206 -0
  114. package/test-aplicacion.con-logisession/controllers/qwenQueueController.js +197 -0
  115. package/test-aplicacion.con-logisession/controllers/test.js +0 -0
  116. package/test-aplicacion.con-logisession/controllers/tracking/EventsNoFinishController.js +78 -0
  117. package/test-aplicacion.con-logisession/controllers/tracking/TrackingController.js +412 -0
  118. package/test-aplicacion.con-logisession/controllers/tracking/TrackingControllerWithLoadModel.js +437 -0
  119. package/test-aplicacion.con-logisession/hooks/admin-hooks.js +20 -0
  120. package/test-aplicacion.con-logisession/hooks/general-hooks.js +97 -0
  121. package/test-aplicacion.con-logisession/hooks/queue-hooks.js +64 -0
  122. package/test-aplicacion.con-logisession/hooks/route-directory-hooks.js +38 -0
  123. package/test-aplicacion.con-logisession/hooks/security-hooks.js +24 -0
  124. package/test-aplicacion.con-logisession/insitu-admin-client/README.md +69 -0
  125. package/test-aplicacion.con-logisession/insitu-admin-client/package.json +23 -0
  126. package/test-aplicacion.con-logisession/insitu-admin-client.js +257 -0
  127. package/test-aplicacion.con-logisession/models/ExampleModel.js +88 -0
  128. package/test-aplicacion.con-logisession/models/QueueJobModel.js +263 -0
  129. package/test-aplicacion.con-logisession/models/TokenModel.js +207 -0
  130. package/test-aplicacion.con-logisession/models/auth/AuthModel.js +66 -0
  131. package/test-aplicacion.con-logisession/models/auth/UserModel.js +189 -0
  132. package/test-aplicacion.con-logisession/models/tracking/CompletedCartModel.js +213 -0
  133. package/test-aplicacion.con-logisession/models/tracking/EventModel.js +366 -0
  134. package/test-aplicacion.con-logisession/models/tracking/EventsNoFinishModel.js +131 -0
  135. package/test-aplicacion.con-logisession/models/tracking/SessionModel.js +360 -0
  136. package/test-aplicacion.con-logisession/models/tracking/SiteFlowModel.js +286 -0
  137. package/test-aplicacion.con-logisession/models/tracking/TokenModel.js +207 -0
  138. package/test-aplicacion.con-logisession/package-lock.json +3313 -0
  139. package/test-aplicacion.con-logisession/package.json +32 -0
  140. package/test-aplicacion.con-logisession/public/blackcoffee-welcome/index.html +1339 -0
  141. package/test-aplicacion.con-logisession/public/css/style.css +64 -0
  142. package/test-aplicacion.con-logisession/public/ejemplo-estatica/index.html +18 -0
  143. package/test-aplicacion.con-logisession/public/ejemplo-estatica/script.js +16 -0
  144. package/test-aplicacion.con-logisession/public/ejemplo-estatica/styles.css +43 -0
  145. package/test-aplicacion.con-logisession/public/images/logo.svg +7 -0
  146. package/test-aplicacion.con-logisession/public/js/main.js +67 -0
  147. package/test-aplicacion.con-logisession/routes/analytics-routes.json +8 -0
  148. package/test-aplicacion.con-logisession/routes/auth-routes.json +98 -0
  149. package/test-aplicacion.con-logisession/routes/blackcoffee-welcome-routes.json +20 -0
  150. package/test-aplicacion.con-logisession/routes/duplicate-test-routes.json.disabled +16 -0
  151. package/test-aplicacion.con-logisession/routes/ejemplo-estatica-routes.json +11 -0
  152. package/test-aplicacion.con-logisession/routes/endpoints-routes.json +8 -0
  153. package/test-aplicacion.con-logisession/routes/ia-queue-routes.json +26 -0
  154. package/test-aplicacion.con-logisession/routes/product-routes.json.disabled +20 -0
  155. package/test-aplicacion.con-logisession/routes/queue-routes.json +32 -0
  156. package/test-aplicacion.con-logisession/routes/qwen-routes.json +14 -0
  157. package/test-aplicacion.con-logisession/routes/static-routes.json +29 -0
  158. package/test-aplicacion.con-logisession/routes/tracking-routes.json +58 -0
  159. package/test-aplicacion.con-logisession/routes/tracking-with-loadmodel-routes.json +51 -0
  160. package/test-aplicacion.con-logisession/utils/dbAdapter.js +88 -0
  161. package/test-aplicacion.con-logisession/utils/qbWrapper.js +4 -0
  162. package/test-aplicacion.con-logisession/utils/queueProcessor.js +305 -0
  163. package/test-aplicacion.con-logisession/utils/qwenRulesService.js +131 -0
  164. package/test-aplicacion.con-logisession/utils/tokenHelper.js +22 -0
  165. package/test-aplicacion.con-logisession/views/auth/dashboard.html +443 -0
  166. package/test-aplicacion.con-logisession/views/auth/forgot-password.html +200 -0
  167. package/test-aplicacion.con-logisession/views/auth/login.html +213 -0
  168. package/test-aplicacion.con-logisession/views/auth/register.html +294 -0
  169. package/test-aplicacion.con-logisession/views/contact/form.html +47 -0
  170. package/test-aplicacion.con-logisession/views/products/index.html +39 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Controlador para vistas de autenticación
3
+ * AuthViewController.js
4
+ */
5
+
6
+ const { ControllerBase } = require('insitu-js');
7
+
8
+ class AuthViewController extends ControllerBase {
9
+ constructor(options = {}) {
10
+ super(options);
11
+ }
12
+
13
+ /**
14
+ * Muestra la página de inicio de sesión
15
+ * GET /login
16
+ */
17
+ async showLogin(req, res) {
18
+ try {
19
+ // Preparar datos para la vista
20
+ this.set('title', 'Iniciar Sesión');
21
+ this.set('message', 'Por favor, ingresa tus credenciales para continuar');
22
+
23
+ // Renderizar la vista
24
+ const html = this.view('auth/login', {
25
+ title: 'Iniciar Sesión',
26
+ message: 'Por favor, ingresa tus credenciales para continuar'
27
+ });
28
+
29
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
30
+ res.end(html);
31
+ } catch (error) {
32
+ console.error('Error en showLogin:', error);
33
+ res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
34
+ res.end(`
35
+ <!DOCTYPE html>
36
+ <html>
37
+ <head>
38
+ <title>Error</title>
39
+ <meta charset="utf-8">
40
+ </head>
41
+ <body>
42
+ <h1>Error al cargar la página de inicio de sesión</h1>
43
+ <p>${error.message}</p>
44
+ <a href="/">Volver al inicio</a>
45
+ </body>
46
+ </html>
47
+ `);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Muestra la página de registro
53
+ * GET /register
54
+ */
55
+ async showRegister(req, res) {
56
+ try {
57
+ // Preparar datos para la vista
58
+ this.set('title', 'Registrarse');
59
+ this.set('message', 'Crea una cuenta para comenzar');
60
+
61
+ // Renderizar la vista
62
+ const html = this.view('auth/register', {
63
+ title: 'Registrarse',
64
+ message: 'Crea una cuenta para comenzar'
65
+ });
66
+
67
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
68
+ res.end(html);
69
+ } catch (error) {
70
+ console.error('Error en showRegister:', error);
71
+ res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
72
+ res.end(`
73
+ <!DOCTYPE html>
74
+ <html>
75
+ <head>
76
+ <title>Error</title>
77
+ <meta charset="utf-8">
78
+ </head>
79
+ <body>
80
+ <h1>Error al cargar la página de registro</h1>
81
+ <p>${error.message}</p>
82
+ <a href="/">Volver al inicio</a>
83
+ </body>
84
+ </html>
85
+ `);
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Muestra la página de olvido de contraseña
91
+ * GET /forgot-password
92
+ */
93
+ async showForgotPassword(req, res) {
94
+ try {
95
+ // Preparar datos para la vista
96
+ this.set('title', 'Recuperar Contraseña');
97
+ this.set('message', 'Ingresa tu email para recuperar tu contraseña');
98
+
99
+ // Renderizar la vista
100
+ const html = this.view('auth/forgot-password', {
101
+ title: 'Recuperar Contraseña',
102
+ message: 'Ingresa tu email para recuperar tu contraseña'
103
+ });
104
+
105
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
106
+ res.end(html);
107
+ } catch (error) {
108
+ console.error('Error en showForgotPassword:', error);
109
+ res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
110
+ res.end(`
111
+ <!DOCTYPE html>
112
+ <html>
113
+ <head>
114
+ <title>Error</title>
115
+ <meta charset="utf-8">
116
+ </head>
117
+ <body>
118
+ <h1>Error al cargar la página de recuperación de contraseña</h1>
119
+ <p>${error.message}</p>
120
+ <a href="/">Volver al inicio</a>
121
+ </body>
122
+ </html>
123
+ `);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Muestra la página de dashboard (después del login)
129
+ * GET /dashboard
130
+ */
131
+ async showDashboard(req, res) {
132
+ try {
133
+ // Mostrar información de depuración sobre la sesión
134
+ console.log('[DEBUG] showDashboard - req.session:', req.session);
135
+ console.log('[DEBUG] showDashboard - req.session.data:', req.session?.data);
136
+ console.log('[DEBUG] showDashboard - req.session.data.authenticated:', req.session?.data?.authenticated);
137
+
138
+ // Verificar si el usuario está autenticado a través de la sesión
139
+ if (!req.session || !req.session.data || !req.session.data.authenticated) {
140
+ // Redirigir al login si no está autenticado
141
+ console.log('[DEBUG] showDashboard - No autenticado, redirigiendo a /login');
142
+ res.writeHead(302, { 'Location': '/login' });
143
+ res.end();
144
+ return;
145
+ }
146
+
147
+ // Obtener información del usuario desde la sesión
148
+ const sessionData = req.session.data;
149
+ const userId = sessionData.userId;
150
+
151
+ // Obtener información del usuario
152
+ const AuthModel = require('../../models/auth/AuthModel');
153
+ const authModel = new AuthModel();
154
+ const user = await authModel.getUserById(userId);
155
+
156
+ // Preparar datos para la vista
157
+ this.set('title', 'Panel de Control');
158
+ this.set('user', user);
159
+
160
+ // Renderizar la vista
161
+ const html = this.view('auth/dashboard', {
162
+ title: 'Panel de Control',
163
+ user: user
164
+ });
165
+
166
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
167
+ res.end(html);
168
+ } catch (error) {
169
+ console.error('Error en showDashboard:', error);
170
+ res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
171
+ res.end(`
172
+ <!DOCTYPE html>
173
+ <html>
174
+ <head>
175
+ <title>Error</title>
176
+ <meta charset="utf-8">
177
+ </head>
178
+ <body>
179
+ <h1>Error al cargar el panel de control</h1>
180
+ <p>${error.message}</p>
181
+ <a href="/login">Ir al inicio de sesión</a>
182
+ </body>
183
+ </html>
184
+ `);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Método para validar token
190
+ */
191
+ async validateToken(token) {
192
+ try {
193
+ const { validateToken } = require('../../utils/tokenHelper');
194
+ const isValid = await validateToken(token);
195
+ return isValid;
196
+ } catch (error) {
197
+ console.error('Error validando token:', error);
198
+ return false;
199
+ }
200
+ }
201
+ }
202
+
203
+ // Exportar métodos individualmente para que RouteLoader pueda acceder a ellos
204
+ const controllerInstance = new AuthViewController();
205
+
206
+ module.exports = {
207
+ showLogin: (req, res) => {
208
+ controllerInstance.setRequestResponse(req, res);
209
+ controllerInstance.showLogin(req, res);
210
+ },
211
+ showRegister: (req, res) => {
212
+ controllerInstance.setRequestResponse(req, res);
213
+ controllerInstance.showRegister(req, res);
214
+ },
215
+ showForgotPassword: (req, res) => {
216
+ controllerInstance.setRequestResponse(req, res);
217
+ controllerInstance.showForgotPassword(req, res);
218
+ },
219
+ showDashboard: (req, res) => {
220
+ controllerInstance.setRequestResponse(req, res);
221
+ controllerInstance.showDashboard(req, res);
222
+ }
223
+ };
@@ -0,0 +1,66 @@
1
+ const { ControllerBase } = require('insitu-js');
2
+
3
+ class EndpointController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ // Método para listar todos los endpoints registrados
9
+ async listEndpoints(req, res) {
10
+ try {
11
+ let endpoints = [];
12
+
13
+ // Usar el mapa global registeredEndpoints que contiene la información completa de las rutas
14
+ for (const [key, endpoint] of global.registeredEndpoints) {
15
+ endpoints.push(endpoint);
16
+ }
17
+
18
+ // Ordenar los endpoints por método y luego por ruta
19
+ endpoints.sort((a, b) => {
20
+ // Primero ordenar por método HTTP
21
+ const methodOrder = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];
22
+ const methodComparison = methodOrder.indexOf(a.method.toUpperCase()) - methodOrder.indexOf(b.method.toUpperCase());
23
+
24
+ if (methodComparison !== 0) {
25
+ return methodComparison;
26
+ }
27
+
28
+ // Si tienen el mismo método, ordenar por ruta
29
+ return a.path.localeCompare(b.path);
30
+ });
31
+
32
+ // Preparar respuesta
33
+ const response = {
34
+ success: true,
35
+ count: endpoints.length,
36
+ endpoints: endpoints
37
+ };
38
+
39
+ // Enviar respuesta JSON
40
+ res.writeHead(200, {
41
+ 'Content-Type': 'application/json',
42
+ 'Access-Control-Allow-Origin': '*',
43
+ 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
44
+ 'Access-Control-Allow-Headers': 'Content-Type, Authorization'
45
+ });
46
+ res.end(JSON.stringify(response, null, 2));
47
+ } catch (error) {
48
+ console.error('Error al listar endpoints:', error);
49
+
50
+ this.json(res, {
51
+ success: false,
52
+ error: error.message
53
+ }, 500);
54
+ }
55
+ }
56
+ }
57
+
58
+ // Exportar métodos individualmente para que RouteLoader pueda acceder a ellos
59
+ const controllerInstance = new EndpointController();
60
+
61
+ module.exports = {
62
+ listEndpoints: (req, res) => {
63
+ controllerInstance.setRequestResponse(req, res);
64
+ controllerInstance.listEndpoints(req, res);
65
+ }
66
+ };
@@ -0,0 +1,183 @@
1
+ const { ControllerBase } = require('insitu-js');
2
+ const ProductModel = require('../models/ExampleModel');
3
+
4
+ class ProductController extends ControllerBase {
5
+ constructor(options = {}) {
6
+ super(options);
7
+ this.model = new ProductModel();
8
+ }
9
+
10
+ // Método para mostrar la página principal con productos
11
+ async index(req, res) {
12
+ try {
13
+ const products = await this.model.getAllProducts();
14
+
15
+ // Preparar datos para la vista
16
+ this.set('title', 'Tienda de Productos');
17
+ this.set('products', products);
18
+ this.set('activePage', 'home');
19
+
20
+ // Renderizar la vista
21
+ const html = this.view('products/index', {
22
+ title: 'Tienda de Productos',
23
+ products: products,
24
+ activePage: 'home'
25
+ });
26
+
27
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
28
+ res.end(html);
29
+ } catch (error) {
30
+ this.json(res, {
31
+ success: false,
32
+ error: error.message
33
+ }, 500);
34
+ }
35
+ }
36
+
37
+ // Método para obtener productos en formato JSON
38
+ async getAllProducts(req, res) {
39
+ try {
40
+ const products = await this.model.getAllProducts();
41
+
42
+ // Devolver directamente el array de productos para compatibilidad con el frontend
43
+ res.writeHead(200, { 'Content-Type': 'application/json' });
44
+ res.end(JSON.stringify(products));
45
+ } catch (error) {
46
+ this.json(res, {
47
+ success: false,
48
+ error: error.message
49
+ }, 500);
50
+ }
51
+ }
52
+
53
+ // Método para obtener un producto específico por ID
54
+ async getProductById(req, res) {
55
+ try {
56
+ const id = this.input('id', null);
57
+ if (!id) {
58
+ return this.json(res, {
59
+ success: false,
60
+ error: 'ID de producto es requerido'
61
+ }, 400);
62
+ }
63
+
64
+ const product = await this.model.getProductById(id);
65
+ if (!product) {
66
+ return this.json(res, {
67
+ success: false,
68
+ error: 'Producto no encontrado'
69
+ }, 404);
70
+ }
71
+
72
+ this.json(res, {
73
+ success: true,
74
+ data: product
75
+ });
76
+ } catch (error) {
77
+ this.json(res, {
78
+ success: false,
79
+ error: error.message
80
+ }, 500);
81
+ }
82
+ }
83
+
84
+ // Método para crear un nuevo producto
85
+ async createProduct(req, res) {
86
+ try {
87
+ // En una implementación real, aquí obtendríamos los datos del cuerpo de la solicitud
88
+ const productData = {
89
+ name: this.input('name', ''),
90
+ description: this.input('description', ''),
91
+ price: parseFloat(this.input('price', 0)),
92
+ category: this.input('category', '')
93
+ };
94
+
95
+ const newProduct = await this.model.createProduct(productData);
96
+
97
+ this.json(res, {
98
+ success: true,
99
+ data: newProduct
100
+ }, 201);
101
+ } catch (error) {
102
+ this.json(res, {
103
+ success: false,
104
+ error: error.message
105
+ }, 500);
106
+ }
107
+ }
108
+
109
+ // Método para mostrar la página de contacto
110
+ async showContact(req, res) {
111
+ try {
112
+ this.set('title', 'Contacto');
113
+ this.set('activePage', 'contact');
114
+
115
+ const html = this.view('contact/form', {
116
+ title: 'Contacto',
117
+ activePage: 'contact'
118
+ });
119
+
120
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
121
+ res.end(html);
122
+ } catch (error) {
123
+ this.json(res, {
124
+ success: false,
125
+ error: error.message
126
+ }, 500);
127
+ }
128
+ }
129
+
130
+ // Método para manejar el envío del formulario de contacto
131
+ async handleContact(req, res) {
132
+ try {
133
+ const contactData = {
134
+ name: this.input('name', ''),
135
+ email: this.input('email', ''),
136
+ message: this.input('message', '')
137
+ };
138
+
139
+ // Aquí iría la lógica para procesar el formulario de contacto
140
+ // Por ahora, simplemente devolvemos éxito
141
+
142
+ this.json(res, {
143
+ success: true,
144
+ message: 'Mensaje recibido correctamente'
145
+ });
146
+ } catch (error) {
147
+ this.json(res, {
148
+ success: false,
149
+ error: error.message
150
+ }, 500);
151
+ }
152
+ }
153
+ }
154
+
155
+ // Exportar métodos individualmente para que RouteLoader pueda acceder a ellos
156
+ const controllerInstance = new ProductController();
157
+
158
+ module.exports = {
159
+ index: (req, res) => {
160
+ controllerInstance.setRequestResponse(req, res);
161
+ controllerInstance.index(req, res);
162
+ },
163
+ getAllProducts: (req, res) => {
164
+ controllerInstance.setRequestResponse(req, res);
165
+ controllerInstance.getAllProducts(req, res);
166
+ },
167
+ getProductById: (req, res) => {
168
+ controllerInstance.setRequestResponse(req, res);
169
+ controllerInstance.getProductById(req, res);
170
+ },
171
+ createProduct: (req, res) => {
172
+ controllerInstance.setRequestResponse(req, res);
173
+ controllerInstance.createProduct(req, res);
174
+ },
175
+ showContact: (req, res) => {
176
+ controllerInstance.setRequestResponse(req, res);
177
+ controllerInstance.showContact(req, res);
178
+ },
179
+ handleContact: (req, res) => {
180
+ controllerInstance.setRequestResponse(req, res);
181
+ controllerInstance.handleContact(req, res);
182
+ }
183
+ };