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.
- package/CHANGELOG.md +664 -0
- package/LICENSE +201 -0
- package/NOTICE +25 -0
- package/README.md +246 -0
- package/apps.zip +0 -0
- package/bin/adminclient +105 -0
- package/bin/blackcoffee +133 -0
- package/cli/admin-users.js +282 -0
- package/cli/commands/app.js +561 -0
- package/cli/commands/config.js +182 -0
- package/cli/commands/db.js +257 -0
- package/cli/commands/server.js +200 -0
- package/config/applications.json +5 -0
- package/config/database.json +28 -0
- package/config/database.json.example +23 -0
- package/config/server.json +32 -0
- package/controllers/admin/AdminController.js +529 -0
- package/controllers/admin/AdminViewController.js +90 -0
- package/controllers/admin/AuthController.js +293 -0
- package/controllers/admin/DatabaseAdminController.js +218 -0
- package/core/SQLiteAdapter.js +333 -0
- package/core/appLoader.js +385 -0
- package/core/databasePoolManager.js +431 -0
- package/core/hotReload.js +363 -0
- package/data/ADMIN-README.md +145 -0
- package/data/CHANGELOG.md +48 -0
- package/data/GTK3-NODE-PROPOSALS.md +410 -0
- package/data/admin-db.js +150 -0
- package/data/admin-gui.js +452 -0
- package/data/blackcoffee_admin.db-shm +0 -0
- package/data/blackcoffee_admin.db-wal +0 -0
- package/data/migrations/001_create_admin_users.sql +33 -0
- package/docs/APP_HOOKS_HANDLER.md +432 -0
- package/docs/APP_HOOKS_REQUIREMENTS.md +588 -0
- package/docs/ARCHITECTURE.md +435 -0
- package/docs/CREAR_APP_Y_USAR_POOLS.md +1595 -0
- package/docs/EVENTS_APP_MANUAL.md +289 -0
- package/docs/INSITU_BINARY_UPLOAD_PROPOSAL.md +186 -0
- package/docs/INSITU_FIREWALL_EXCEPTION.md +187 -0
- package/docs/ROADMAP.md +242 -0
- package/docs/ROADMAP.md.backup +243 -0
- package/includes/404-hooks.js +423 -0
- package/includes/adminAuth.js +214 -0
- package/includes/adminExtension.js +53 -0
- package/includes/appHooks.js +302 -0
- package/includes/initAdminDb.js +115 -0
- package/includes/routeLoader.js +67 -0
- package/includes/sessions.js +223 -0
- package/issues/001-duplicate-module-loading.md +92 -0
- package/manuales/ADMIN_EXTENSION_COMMANDS_MANUAL.md +261 -0
- package/manuales/ADMIN_EXTENSION_HOOK_EXAMPLE.md +28 -0
- package/manuales/ADMIN_EXTENSION_INTEGRATION_MANUAL.md +232 -0
- package/manuales/CACHE_REGEX_COMMANDS.md +136 -0
- package/manuales/CACHE_SYSTEM_MAP.md +206 -0
- package/manuales/CREACION_DE_CONTROLADORES_INSITU.md +383 -0
- package/manuales/QUEUE_CLI_MODULE_MANUAL.md +289 -0
- package/manuales/QUEUE_SYSTEM_MANUAL.md +320 -0
- package/manuales/ROUTE_CACHE_MODULE_MANUAL.md +205 -0
- package/manuales/SESSION_MANAGER_GUIDE.md +529 -0
- package/manuales/SESSION_SECURITY_FLAGS.md +174 -0
- package/manuales/WAF_MODULE_MANUAL.md +229 -0
- package/manuales/after_route_handler_filter_example.md +116 -0
- package/manuales/after_route_handler_usage.md +130 -0
- package/manuales/an/303/241lisis-completo-insitu-framework.md +213 -0
- package/manuales/async_hooks_promises_guide.md +325 -0
- package/manuales/before_route_handler_filter_example.md +97 -0
- package/manuales/before_route_handler_usage.md +122 -0
- package/manuales/hooks_chaining_conditions_guide.md +261 -0
- package/manuales/hooks_filters_documentation.md +493 -0
- package/manuales/hooks_filters_documentation_en.md +493 -0
- package/manuales/hooks_vs_middlewares_comparison.md +87 -0
- package/manuales/manual-mvc-completo.md +934 -0
- package/manuales/modulos_administracion.md +89 -0
- package/manuales/router_execution_points.md +74 -0
- package/manuales/static_file_hooks_usage.md +222 -0
- package/models/AdminUserModel.js +132 -0
- package/package.json +45 -0
- package/programatically/PRoutes.js +89 -0
- package/programatically/initFlow.js +211 -0
- package/public/admin/css/db-pools.css +336 -0
- package/public/admin/css/styles.css +310 -0
- package/public/admin/database.html +312 -0
- package/public/admin/index.html +116 -0
- package/public/admin/js/app.js +470 -0
- package/public/admin/js/db-pools.js +253 -0
- package/public/admin/login.html +278 -0
- package/public/assets/css/styles.css +477 -0
- package/public/assets/js/main.js +89 -0
- package/public/index.html +136 -0
- package/public/templates/404.html +158 -0
- package/routes/admin-views.json +20 -0
- package/routes/admin.json +38 -0
- package/routes/auth.json +32 -0
- package/routes/static.json +18 -0
- package/server.js +299 -0
- package/test-aplicacion.con-logisession/BlackCoffee.js +226 -0
- package/test-aplicacion.con-logisession/SSL_SETUP.md +53 -0
- package/test-aplicacion.con-logisession/certs/ca-certificate.pem +32 -0
- package/test-aplicacion.con-logisession/certs/ca-private-key.pem +52 -0
- package/test-aplicacion.con-logisession/certs/certificate-2048.pem +22 -0
- package/test-aplicacion.con-logisession/certs/certificate.pem +32 -0
- package/test-aplicacion.con-logisession/certs/private-key-2048.pem +28 -0
- package/test-aplicacion.con-logisession/certs/private-key.pem +52 -0
- package/test-aplicacion.con-logisession/config/iaQueueSetup.js +84 -0
- package/test-aplicacion.con-logisession/config/qwen-rules.json +39 -0
- package/test-aplicacion.con-logisession/controllers/analyticsController.js +117 -0
- package/test-aplicacion.con-logisession/controllers/auth/AdminAuthController.js +142 -0
- package/test-aplicacion.con-logisession/controllers/auth/AuthController.js +439 -0
- package/test-aplicacion.con-logisession/controllers/auth/AuthViewController.js +223 -0
- package/test-aplicacion.con-logisession/controllers/endpointController.js +66 -0
- package/test-aplicacion.con-logisession/controllers/example.js +183 -0
- package/test-aplicacion.con-logisession/controllers/iaQueueController.js +367 -0
- package/test-aplicacion.con-logisession/controllers/queueController.js +206 -0
- package/test-aplicacion.con-logisession/controllers/qwenQueueController.js +197 -0
- package/test-aplicacion.con-logisession/controllers/test.js +0 -0
- package/test-aplicacion.con-logisession/controllers/tracking/EventsNoFinishController.js +78 -0
- package/test-aplicacion.con-logisession/controllers/tracking/TrackingController.js +412 -0
- package/test-aplicacion.con-logisession/controllers/tracking/TrackingControllerWithLoadModel.js +437 -0
- package/test-aplicacion.con-logisession/hooks/admin-hooks.js +20 -0
- package/test-aplicacion.con-logisession/hooks/general-hooks.js +97 -0
- package/test-aplicacion.con-logisession/hooks/queue-hooks.js +64 -0
- package/test-aplicacion.con-logisession/hooks/route-directory-hooks.js +38 -0
- package/test-aplicacion.con-logisession/hooks/security-hooks.js +24 -0
- package/test-aplicacion.con-logisession/insitu-admin-client/README.md +69 -0
- package/test-aplicacion.con-logisession/insitu-admin-client/package.json +23 -0
- package/test-aplicacion.con-logisession/insitu-admin-client.js +257 -0
- package/test-aplicacion.con-logisession/models/ExampleModel.js +88 -0
- package/test-aplicacion.con-logisession/models/QueueJobModel.js +263 -0
- package/test-aplicacion.con-logisession/models/TokenModel.js +207 -0
- package/test-aplicacion.con-logisession/models/auth/AuthModel.js +66 -0
- package/test-aplicacion.con-logisession/models/auth/UserModel.js +189 -0
- package/test-aplicacion.con-logisession/models/tracking/CompletedCartModel.js +213 -0
- package/test-aplicacion.con-logisession/models/tracking/EventModel.js +366 -0
- package/test-aplicacion.con-logisession/models/tracking/EventsNoFinishModel.js +131 -0
- package/test-aplicacion.con-logisession/models/tracking/SessionModel.js +360 -0
- package/test-aplicacion.con-logisession/models/tracking/SiteFlowModel.js +286 -0
- package/test-aplicacion.con-logisession/models/tracking/TokenModel.js +207 -0
- package/test-aplicacion.con-logisession/package-lock.json +3313 -0
- package/test-aplicacion.con-logisession/package.json +32 -0
- package/test-aplicacion.con-logisession/public/blackcoffee-welcome/index.html +1339 -0
- package/test-aplicacion.con-logisession/public/css/style.css +64 -0
- package/test-aplicacion.con-logisession/public/ejemplo-estatica/index.html +18 -0
- package/test-aplicacion.con-logisession/public/ejemplo-estatica/script.js +16 -0
- package/test-aplicacion.con-logisession/public/ejemplo-estatica/styles.css +43 -0
- package/test-aplicacion.con-logisession/public/images/logo.svg +7 -0
- package/test-aplicacion.con-logisession/public/js/main.js +67 -0
- package/test-aplicacion.con-logisession/routes/analytics-routes.json +8 -0
- package/test-aplicacion.con-logisession/routes/auth-routes.json +98 -0
- package/test-aplicacion.con-logisession/routes/blackcoffee-welcome-routes.json +20 -0
- package/test-aplicacion.con-logisession/routes/duplicate-test-routes.json.disabled +16 -0
- package/test-aplicacion.con-logisession/routes/ejemplo-estatica-routes.json +11 -0
- package/test-aplicacion.con-logisession/routes/endpoints-routes.json +8 -0
- package/test-aplicacion.con-logisession/routes/ia-queue-routes.json +26 -0
- package/test-aplicacion.con-logisession/routes/product-routes.json.disabled +20 -0
- package/test-aplicacion.con-logisession/routes/queue-routes.json +32 -0
- package/test-aplicacion.con-logisession/routes/qwen-routes.json +14 -0
- package/test-aplicacion.con-logisession/routes/static-routes.json +29 -0
- package/test-aplicacion.con-logisession/routes/tracking-routes.json +58 -0
- package/test-aplicacion.con-logisession/routes/tracking-with-loadmodel-routes.json +51 -0
- package/test-aplicacion.con-logisession/utils/dbAdapter.js +88 -0
- package/test-aplicacion.con-logisession/utils/qbWrapper.js +4 -0
- package/test-aplicacion.con-logisession/utils/queueProcessor.js +305 -0
- package/test-aplicacion.con-logisession/utils/qwenRulesService.js +131 -0
- package/test-aplicacion.con-logisession/utils/tokenHelper.js +22 -0
- package/test-aplicacion.con-logisession/views/auth/dashboard.html +443 -0
- package/test-aplicacion.con-logisession/views/auth/forgot-password.html +200 -0
- package/test-aplicacion.con-logisession/views/auth/login.html +213 -0
- package/test-aplicacion.con-logisession/views/auth/register.html +294 -0
- package/test-aplicacion.con-logisession/views/contact/form.html +47 -0
- 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
|
+
};
|