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,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
+ ]
@@ -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 };