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,158 @@
|
|
|
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>404 - No Encontrado | BlackCoffee</title>
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
margin: 0;
|
|
10
|
+
padding: 0;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
17
|
+
color: #f5f5f5;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.container {
|
|
25
|
+
text-align: center;
|
|
26
|
+
padding: 2rem;
|
|
27
|
+
max-width: 600px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.error-code {
|
|
31
|
+
font-size: 8rem;
|
|
32
|
+
font-weight: bold;
|
|
33
|
+
background: linear-gradient(135deg, #6f4e37 0%, #c9a87c 100%);
|
|
34
|
+
-webkit-background-clip: text;
|
|
35
|
+
-webkit-text-fill-color: transparent;
|
|
36
|
+
background-clip: text;
|
|
37
|
+
line-height: 1;
|
|
38
|
+
margin-bottom: 1rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.error-title {
|
|
42
|
+
font-size: 2rem;
|
|
43
|
+
margin-bottom: 1.5rem;
|
|
44
|
+
color: #c9a87c;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.error-message {
|
|
48
|
+
font-size: 1.1rem;
|
|
49
|
+
color: #a0a0a0;
|
|
50
|
+
margin-bottom: 2rem;
|
|
51
|
+
line-height: 1.6;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.error-details {
|
|
55
|
+
background: rgba(255, 255, 255, 0.05);
|
|
56
|
+
padding: 1.5rem;
|
|
57
|
+
border-radius: 12px;
|
|
58
|
+
border: 1px solid rgba(201, 168, 124, 0.2);
|
|
59
|
+
margin-bottom: 2rem;
|
|
60
|
+
text-align: left;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.error-details p {
|
|
64
|
+
margin-bottom: 0.5rem;
|
|
65
|
+
font-size: 0.9rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.error-details strong {
|
|
69
|
+
color: #c9a87c;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.btn {
|
|
73
|
+
display: inline-block;
|
|
74
|
+
padding: 1rem 2rem;
|
|
75
|
+
background: linear-gradient(135deg, #6f4e37 0%, #c9a87c 100%);
|
|
76
|
+
color: #f5f5f5;
|
|
77
|
+
text-decoration: none;
|
|
78
|
+
border-radius: 8px;
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
transition: transform 0.3s, box-shadow 0.3s;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.btn:hover {
|
|
84
|
+
transform: translateY(-3px);
|
|
85
|
+
box-shadow: 0 10px 30px rgba(111, 78, 55, 0.4);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.coffee-icon {
|
|
89
|
+
font-size: 4rem;
|
|
90
|
+
margin-bottom: 1rem;
|
|
91
|
+
animation: bounce 2s infinite;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@keyframes bounce {
|
|
95
|
+
0%, 100% {
|
|
96
|
+
transform: translateY(0);
|
|
97
|
+
}
|
|
98
|
+
50% {
|
|
99
|
+
transform: translateY(-20px);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.footer {
|
|
104
|
+
margin-top: 3rem;
|
|
105
|
+
padding-top: 2rem;
|
|
106
|
+
border-top: 1px solid rgba(201, 168, 124, 0.2);
|
|
107
|
+
color: #666;
|
|
108
|
+
font-size: 0.9rem;
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
111
|
+
</head>
|
|
112
|
+
<body>
|
|
113
|
+
<div class="container">
|
|
114
|
+
<div class="coffee-icon">β</div>
|
|
115
|
+
<div class="error-code">404</div>
|
|
116
|
+
<h1 class="error-title">Β‘Ups! No encontramos lo que buscas</h1>
|
|
117
|
+
<p class="error-message">
|
|
118
|
+
Parece que te has perdido en el camino.
|
|
119
|
+
La pΓ‘gina o recurso que estΓ‘s buscando no existe en BlackCoffee.
|
|
120
|
+
</p>
|
|
121
|
+
|
|
122
|
+
<div class="error-details">
|
|
123
|
+
<p><strong>Tipo:</strong> <span id="errorType">Ruta no encontrada</span></p>
|
|
124
|
+
<p><strong>URL solicitada:</strong> <span id="requestedPath">/</span></p>
|
|
125
|
+
<p><strong>MΓ©todo:</strong> <span id="requestMethod">GET</span></p>
|
|
126
|
+
<p><strong>Timestamp:</strong> <span id="timestamp">-</span></p>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<a href="/" class="btn">Volver al Inicio</a>
|
|
130
|
+
|
|
131
|
+
<div class="footer">
|
|
132
|
+
<p>BlackCoffee v1.1.0 - Construido con Insitu Framework</p>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<script>
|
|
137
|
+
// Datos del error (se inyectan desde el servidor)
|
|
138
|
+
const errorData = window.errorData || {};
|
|
139
|
+
|
|
140
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
141
|
+
// Actualizar detalles si estΓ‘n disponibles
|
|
142
|
+
if (errorData.type) {
|
|
143
|
+
document.getElementById('errorType').textContent =
|
|
144
|
+
errorData.type === 'file' ? 'Archivo no encontrado' : 'Ruta no encontrada';
|
|
145
|
+
}
|
|
146
|
+
if (errorData.path) {
|
|
147
|
+
document.getElementById('requestedPath').textContent = errorData.path;
|
|
148
|
+
}
|
|
149
|
+
if (errorData.method) {
|
|
150
|
+
document.getElementById('requestMethod').textContent = errorData.method;
|
|
151
|
+
}
|
|
152
|
+
if (errorData.timestamp) {
|
|
153
|
+
document.getElementById('timestamp').textContent = errorData.timestamp;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
</script>
|
|
157
|
+
</body>
|
|
158
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"method": "GET",
|
|
4
|
+
"path": "/admin",
|
|
5
|
+
"controller": "controllers/admin/AdminViewController.js",
|
|
6
|
+
"handler": "dashboard"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"method": "GET",
|
|
10
|
+
"path": "/admin/login",
|
|
11
|
+
"controller": "controllers/admin/AdminViewController.js",
|
|
12
|
+
"handler": "login"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"method": "GET",
|
|
16
|
+
"path": "/admin/database",
|
|
17
|
+
"controller": "controllers/admin/AdminViewController.js",
|
|
18
|
+
"handler": "database"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"method": "GET",
|
|
4
|
+
"path": "/api/admin/apps",
|
|
5
|
+
"controller": "controllers/admin/AdminController.js",
|
|
6
|
+
"handler": "listApps"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"method": "GET",
|
|
10
|
+
"path": "/api/admin/apps/:name/:version",
|
|
11
|
+
"controller": "controllers/admin/AdminController.js",
|
|
12
|
+
"handler": "getAppInfo"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"method": "DELETE",
|
|
16
|
+
"path": "/api/admin/apps/:name/:version",
|
|
17
|
+
"controller": "controllers/admin/AdminController.js",
|
|
18
|
+
"handler": "undeployApp"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"method": "POST",
|
|
22
|
+
"path": "/api/admin/apps/:name/:version/restart",
|
|
23
|
+
"controller": "controllers/admin/AdminController.js",
|
|
24
|
+
"handler": "restartApp"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"method": "GET",
|
|
28
|
+
"path": "/api/admin/stats",
|
|
29
|
+
"controller": "controllers/admin/AdminController.js",
|
|
30
|
+
"handler": "getServerStats"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"method": "GET",
|
|
34
|
+
"path": "/api/admin/config",
|
|
35
|
+
"controller": "controllers/admin/AdminController.js",
|
|
36
|
+
"handler": "getConfig"
|
|
37
|
+
}
|
|
38
|
+
]
|
package/routes/auth.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"method": "POST",
|
|
4
|
+
"path": "/api/admin/auth/login",
|
|
5
|
+
"controller": "controllers/admin/AuthController.js",
|
|
6
|
+
"handler": "login"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"method": "POST",
|
|
10
|
+
"path": "/api/admin/auth/logout",
|
|
11
|
+
"controller": "controllers/admin/AuthController.js",
|
|
12
|
+
"handler": "logout"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"method": "GET",
|
|
16
|
+
"path": "/api/admin/auth/verify",
|
|
17
|
+
"controller": "controllers/admin/AuthController.js",
|
|
18
|
+
"handler": "verify"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"method": "GET",
|
|
22
|
+
"path": "/api/admin/auth/me",
|
|
23
|
+
"controller": "controllers/admin/AuthController.js",
|
|
24
|
+
"handler": "getCurrentUser"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"method": "POST",
|
|
28
|
+
"path": "/api/admin/auth/change-password",
|
|
29
|
+
"controller": "controllers/admin/AuthController.js",
|
|
30
|
+
"handler": "changePassword"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"method": "GET",
|
|
4
|
+
"path": "/",
|
|
5
|
+
"static": {
|
|
6
|
+
"dir": "public",
|
|
7
|
+
"index": ["index.html"]
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"method": "GET",
|
|
12
|
+
"path": "/assets",
|
|
13
|
+
"static": {
|
|
14
|
+
"dir": "public/assets",
|
|
15
|
+
"cacheControl": "public, max-age=31536000"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
]
|
package/server.js
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Servidor principal de BlackCoffee
|
|
3
|
+
* Utiliza el framework Insitu
|
|
4
|
+
*
|
|
5
|
+
* ConfiguraciΓ³n:
|
|
6
|
+
* - Puerto: 9791 (por defecto) o especificado mediante la variable de entorno PORT
|
|
7
|
+
* - HTTPS: Habilitado por defecto con certificados autofirmados
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const { APIServer, Firewall } = require('insitu-js');
|
|
13
|
+
const { loadRoutes } = require('./includes/routeLoader');
|
|
14
|
+
const { init: initAdminExtension } = require('./includes/adminExtension');
|
|
15
|
+
const { register: registerInitFlow } = require('./programatically/initFlow');
|
|
16
|
+
const { PRoutes } = require('./programatically/PRoutes');
|
|
17
|
+
const { register: register404Hooks, initMetrics: init404Metrics } = require('./includes/404-hooks');
|
|
18
|
+
const { registerAppHooks } = require('./includes/appHooks');
|
|
19
|
+
const { initAdminAuth } = require('./includes/adminAuth');
|
|
20
|
+
const AppLoader = require('./core/appLoader');
|
|
21
|
+
const HotReloadManager = require('./core/hotReload');
|
|
22
|
+
const DatabasePoolManager = require('./core/databasePoolManager');
|
|
23
|
+
|
|
24
|
+
// ConfiguraciΓ³n del servidor
|
|
25
|
+
const config = {
|
|
26
|
+
// Puerto: usa la variable de entorno PORT o 9791 por defecto
|
|
27
|
+
port: parseInt(process.env.PORT, 10) || 9791,
|
|
28
|
+
host: process.env.HOST || 'localhost',
|
|
29
|
+
|
|
30
|
+
// HTTPS habilitado por defecto
|
|
31
|
+
https: true,
|
|
32
|
+
|
|
33
|
+
// Certificados SSL (por defecto usa 2048 bits)
|
|
34
|
+
key: path.join(__dirname, 'certs', process.env.SSL_KEY || 'key-2048.pem'),
|
|
35
|
+
cert: path.join(__dirname, 'certs', process.env.SSL_CERT || 'cert-2048.pem'),
|
|
36
|
+
|
|
37
|
+
// Timeouts
|
|
38
|
+
requestTimeout: 120000,
|
|
39
|
+
connectionTimeout: 120000,
|
|
40
|
+
maxBodySize: 10 * 1024 * 1024, // 10MB
|
|
41
|
+
|
|
42
|
+
// Consola administrativa
|
|
43
|
+
adminPort: parseInt(process.env.ADMIN_PORT, 10) || 9999,
|
|
44
|
+
adminHost: process.env.ADMIN_HOST || '127.0.0.1'
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Crear instancia del servidor
|
|
48
|
+
const server = new APIServer(config);
|
|
49
|
+
|
|
50
|
+
// ============================================
|
|
51
|
+
// Registrar hooks de App Server
|
|
52
|
+
// ============================================
|
|
53
|
+
registerAppHooks(server.hooks);
|
|
54
|
+
|
|
55
|
+
// Inicializar AppLoader y exponer globalmente
|
|
56
|
+
const appLoader = new AppLoader(server);
|
|
57
|
+
global.appLoader = appLoader;
|
|
58
|
+
server.appLoader = appLoader;
|
|
59
|
+
|
|
60
|
+
console.log('π¦ AppLoader inicializado\n');
|
|
61
|
+
|
|
62
|
+
// ============================================
|
|
63
|
+
// Inicializar autenticaciΓ³n y rutas admin
|
|
64
|
+
// ============================================
|
|
65
|
+
(async () => {
|
|
66
|
+
await initAdminAuth(server);
|
|
67
|
+
|
|
68
|
+
// ============================================
|
|
69
|
+
// Cargar rutas de administraciΓ³n (API)
|
|
70
|
+
// ============================================
|
|
71
|
+
console.log('π Cargando rutas de administraciΓ³n...\n');
|
|
72
|
+
const adminRoutesPath = path.join(__dirname, 'routes', 'admin.json');
|
|
73
|
+
if (fs.existsSync(adminRoutesPath)) {
|
|
74
|
+
const RouteLoader = require('insitu-js/lib/loader/routeLoader');
|
|
75
|
+
const routeLoader = new RouteLoader();
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const adminRoutes = fs.readFileSync(adminRoutesPath, 'utf8');
|
|
79
|
+
const routes = JSON.parse(adminRoutes);
|
|
80
|
+
|
|
81
|
+
for (const route of routes) {
|
|
82
|
+
route.controller = path.join(__dirname, route.controller);
|
|
83
|
+
await routeLoader.loadSingleRoute(server, route);
|
|
84
|
+
console.log(` β
${route.method} ${route.path}`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(' β
Rutas de administraciΓ³n cargadas\n');
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(` β Error cargando rutas admin: ${error.message}\n`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================
|
|
94
|
+
// Cargar aplicaciones desplegadas al startup
|
|
95
|
+
// ============================================
|
|
96
|
+
console.log('π Buscando aplicaciones desplegadas...\n');
|
|
97
|
+
const deployedApps = appLoader.listApps();
|
|
98
|
+
|
|
99
|
+
// Inicializar Hot Reload Manager
|
|
100
|
+
const hotReload = new HotReloadManager(server, {
|
|
101
|
+
enabled: process.env.HOT_RELOAD !== 'false',
|
|
102
|
+
debounceMs: 1500
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Inicializar Database Pool Manager
|
|
106
|
+
const dbPoolManager = new DatabasePoolManager({
|
|
107
|
+
autoConnect: process.env.DB_AUTO_CONNECT !== 'false'
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Exponer globalmente ANTES de cargar las apps
|
|
111
|
+
global.dbPoolManager = dbPoolManager;
|
|
112
|
+
global.hotReload = hotReload;
|
|
113
|
+
|
|
114
|
+
// Cargar configuraciΓ³n de pools desde config/database.json
|
|
115
|
+
const dbConfigPath = path.join(__dirname, 'config', 'database.json');
|
|
116
|
+
if (fs.existsSync(dbConfigPath)) {
|
|
117
|
+
const dbConfig = JSON.parse(fs.readFileSync(dbConfigPath, 'utf8'));
|
|
118
|
+
|
|
119
|
+
if (dbConfig.pools) {
|
|
120
|
+
console.log('ποΈ Cargando pools de base de datos...\n');
|
|
121
|
+
|
|
122
|
+
for (const [poolName, poolConfig] of Object.entries(dbConfig.pools)) {
|
|
123
|
+
try {
|
|
124
|
+
dbPoolManager.registerPool(poolName, poolConfig);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error(` β Error cargando pool '${poolName}':`, error.message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log('');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (deployedApps.length > 0) {
|
|
135
|
+
console.log(`π¦ ${deployedApps.length} aplicaciΓ³n(es) encontrada(s):\n`);
|
|
136
|
+
|
|
137
|
+
for (const app of deployedApps) {
|
|
138
|
+
console.log(` β’ ${app.name} v${app.version}`);
|
|
139
|
+
|
|
140
|
+
const entryPoint = app.manifest?.blackcoffee?.entryPoint || 'routes/static.json';
|
|
141
|
+
const routesPath = path.join(app.path, entryPoint);
|
|
142
|
+
|
|
143
|
+
if (fs.existsSync(routesPath)) {
|
|
144
|
+
appLoader.loadAppRoutes(routesPath, app.name, app.version);
|
|
145
|
+
console.log(` β
Rutas cargadas desde ${entryPoint}`);
|
|
146
|
+
} else {
|
|
147
|
+
console.log(` β οΈ No se encontrΓ³ archivo de rutas: ${routesPath}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (app.manifest?.blackcoffee?.autoStart !== false) {
|
|
151
|
+
console.log(` π Auto-start habilitado`);
|
|
152
|
+
hotReload.watchApp(app.name, app.version);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
console.log('');
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
console.log(' No hay aplicaciones desplegadas\n');
|
|
159
|
+
console.log(' π‘ Usa la CLI para desplegar: blackcoffee app:deploy ./app.tar.gz\n');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ============================================
|
|
163
|
+
// WAF - Web Application Firewall
|
|
164
|
+
// ============================================
|
|
165
|
+
const firewall = new Firewall({
|
|
166
|
+
maxAttempts: 5,
|
|
167
|
+
blockDuration: 900000,
|
|
168
|
+
whitelist: [],
|
|
169
|
+
blacklist: [],
|
|
170
|
+
rules: [
|
|
171
|
+
{
|
|
172
|
+
name: 'sql-injection',
|
|
173
|
+
condition: (req) => {
|
|
174
|
+
const url = req.url.toLowerCase();
|
|
175
|
+
return /(\bselect\b.+\bfrom\b|\binsert\b.+\binto\b|\bupdate\b.+\bset\b|\bdelete\b.+\bfrom\b|\bdrop\b.+\btable\b)/i.test(url);
|
|
176
|
+
},
|
|
177
|
+
action: 'block',
|
|
178
|
+
reason: 'Posible SQL Injection'
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'xss-script',
|
|
182
|
+
condition: (req) => {
|
|
183
|
+
const url = req.url.toLowerCase();
|
|
184
|
+
return /<script|javascript:|onerror=|onload=/i.test(url);
|
|
185
|
+
},
|
|
186
|
+
action: 'block',
|
|
187
|
+
reason: 'Posible XSS Attack'
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
server.use(firewall.middleware());
|
|
193
|
+
console.log('π‘οΈ WAF activado con excepciΓ³n para deploy');
|
|
194
|
+
|
|
195
|
+
// Deploy endpoint (WAF desactivado)
|
|
196
|
+
console.log('π Cargando endpoint de deploy...\n');
|
|
197
|
+
server.addRoute('POST', '/api/admin/apps/deploy', (req, res) => {
|
|
198
|
+
const AdminController = require('./controllers/admin/AdminController');
|
|
199
|
+
AdminController.deployApp(req, res);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Registrar hooks 404
|
|
203
|
+
init404Metrics();
|
|
204
|
+
register404Hooks(server.hooks);
|
|
205
|
+
|
|
206
|
+
// Ruta de health check
|
|
207
|
+
server.addRoute('GET', '/api/health', (req, res) => {
|
|
208
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
209
|
+
res.end(JSON.stringify({
|
|
210
|
+
status: 'ok',
|
|
211
|
+
uptime: process.uptime(),
|
|
212
|
+
timestamp: new Date().toISOString()
|
|
213
|
+
}, null, 2));
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Cargar rutas desde el directorio routes/
|
|
217
|
+
loadRoutes(server)
|
|
218
|
+
.then(() => console.log('β
Rutas externas cargadas correctamente\n'))
|
|
219
|
+
.catch((err) => console.error('β Error cargando rutas externas:', err.message));
|
|
220
|
+
|
|
221
|
+
// Registrar rutas programΓ‘ticas
|
|
222
|
+
registerInitFlow(server);
|
|
223
|
+
PRoutes(server);
|
|
224
|
+
|
|
225
|
+
// Iniciar servidor
|
|
226
|
+
server.start();
|
|
227
|
+
|
|
228
|
+
// Inicializar consola administrativa
|
|
229
|
+
initAdminExtension(server, config);
|
|
230
|
+
|
|
231
|
+
// Mensaje de inicio
|
|
232
|
+
setTimeout(() => {
|
|
233
|
+
console.log(`\nβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ`);
|
|
234
|
+
console.log(`β BlackCoffee - Servidor Iniciado β`);
|
|
235
|
+
console.log(`β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£`);
|
|
236
|
+
console.log(`β Framework: Insitu β`);
|
|
237
|
+
console.log(`β Protocolo: HTTPS (SSL/TLS) β`);
|
|
238
|
+
console.log(`β Host: ${config.host.padEnd(46)}β`);
|
|
239
|
+
console.log(`β Puerto: ${String(config.port).padEnd(46)}β`);
|
|
240
|
+
console.log(`β Certificado: ${path.basename(config.cert).padEnd(45)}β`);
|
|
241
|
+
console.log(`β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£`);
|
|
242
|
+
console.log(`β URLs de acceso: β`);
|
|
243
|
+
console.log(`β β’ https://${config.host}:${config.port}/api/health β`);
|
|
244
|
+
console.log(`β β’ https://${config.host}:${config.port}/admin/login β`);
|
|
245
|
+
console.log(`β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£`);
|
|
246
|
+
console.log(`β Consola Administrativa: β`);
|
|
247
|
+
console.log(`β β’ telnet ${config.adminHost}:${String(config.adminPort).padEnd(32)}β`);
|
|
248
|
+
console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n`);
|
|
249
|
+
}, 500);
|
|
250
|
+
|
|
251
|
+
// Manejo de errores
|
|
252
|
+
server.server.on('error', (error) => {
|
|
253
|
+
if (error.code === 'EADDRINUSE') {
|
|
254
|
+
console.error(`\nβ Error: El puerto ${config.port} ya estΓ‘ en uso.`);
|
|
255
|
+
console.error(` Intenta con otro puerto: PORT=9792 node server.js\n`);
|
|
256
|
+
} else if (error.code === 'ENOENT' && (error.path.includes('key') || error.path.includes('cert'))) {
|
|
257
|
+
console.error(`\nβ Error: No se encontrΓ³ el archivo de certificado: ${error.path}`);
|
|
258
|
+
console.error(` AsegΓΊrate de generar los certificados en el directorio certs/\n`);
|
|
259
|
+
} else {
|
|
260
|
+
console.error(`\nβ Error del servidor:`, error.message, `\n`);
|
|
261
|
+
}
|
|
262
|
+
process.exit(1);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Cierre graceful
|
|
266
|
+
process.on('SIGTERM', () => {
|
|
267
|
+
console.log('\nπ΄ SeΓ±al SIGTERM recibida. Cerrando servidor...');
|
|
268
|
+
if (global.hotReload) {
|
|
269
|
+
console.log('π₯ Cerrando Hot Reload...');
|
|
270
|
+
global.hotReload.closeAll();
|
|
271
|
+
}
|
|
272
|
+
if (global.dbPoolManager) {
|
|
273
|
+
console.log('ποΈ Cerrando Database Pool Manager...');
|
|
274
|
+
global.dbPoolManager.closeAll().then(() => console.log('β
Pools cerrados'));
|
|
275
|
+
}
|
|
276
|
+
server.server.close(() => {
|
|
277
|
+
console.log('β
Servidor cerrado correctamente.');
|
|
278
|
+
process.exit(0);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
process.on('SIGINT', () => {
|
|
283
|
+
console.log('\nπ΄ SeΓ±al SIGINT recibida. Cerrando servidor...');
|
|
284
|
+
if (global.hotReload) {
|
|
285
|
+
console.log('π₯ Cerrando Hot Reload...');
|
|
286
|
+
global.hotReload.closeAll();
|
|
287
|
+
}
|
|
288
|
+
if (global.dbPoolManager) {
|
|
289
|
+
console.log('ποΈ Cerrando Database Pool Manager...');
|
|
290
|
+
global.dbPoolManager.closeAll().then(() => console.log('β
Pools cerrados'));
|
|
291
|
+
}
|
|
292
|
+
server.server.close(() => {
|
|
293
|
+
console.log('β
Servidor cerrado correctamente.');
|
|
294
|
+
process.exit(0);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
})();
|
|
298
|
+
|
|
299
|
+
module.exports = { server, config };
|