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,289 @@
|
|
|
1
|
+
# ☕ events-app - Aplicación de Eventos BlackCoffee
|
|
2
|
+
|
|
3
|
+
## Descripción General
|
|
4
|
+
|
|
5
|
+
**events-app** es una aplicación BlackCoffee que consulta la tabla `events_no_finish` de la base de datos `otrack_db` en MariaDB/MySQL.
|
|
6
|
+
|
|
7
|
+
**Versión:** 1.0.0
|
|
8
|
+
**Pool de Base de Datos:** MySQL-MariaDB
|
|
9
|
+
**Tabla Principal:** events_no_finish
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📁 Estructura de la Aplicación
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
apps/events-app/1.0.0/
|
|
17
|
+
├── package.json # Manifest con configuración BlackCoffee
|
|
18
|
+
├── controllers/
|
|
19
|
+
│ └── EventsController.js # Controlador con 6 endpoints API
|
|
20
|
+
├── models/
|
|
21
|
+
│ └── EventsModel.js # Modelo con consultas a events_no_finish
|
|
22
|
+
├── views/
|
|
23
|
+
│ └── index.html # UI Web con tabla de eventos
|
|
24
|
+
├── routes/
|
|
25
|
+
│ └── api.json # 7 rutas definidas
|
|
26
|
+
└── public/assets/
|
|
27
|
+
├── css/styles.css
|
|
28
|
+
└── js/
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🗄️ Configuración del Pool
|
|
34
|
+
|
|
35
|
+
La aplicación utiliza el pool **`MySQL-MariaDB`** configurado en `config/database.json`:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"MySQL-MariaDB": {
|
|
40
|
+
"type": "mariadb",
|
|
41
|
+
"host": "localhost",
|
|
42
|
+
"port": 3306,
|
|
43
|
+
"user": "root",
|
|
44
|
+
"password": "",
|
|
45
|
+
"database": "otrack_db",
|
|
46
|
+
"connectionLimit": 10
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 📡 Endpoints API
|
|
54
|
+
|
|
55
|
+
| Método | Endpoint | Descripción | Parámetros |
|
|
56
|
+
|--------|----------|-------------|------------|
|
|
57
|
+
| GET | `/events-app/1.0.0/` | Página principal | - |
|
|
58
|
+
| GET | `/events-app/1.0.0/api/events` | Listar eventos | `limit`, `offset`, `order` |
|
|
59
|
+
| GET | `/events-app/1.0.0/api/events/:id` | Obtener evento por ID | `id` |
|
|
60
|
+
| GET | `/events-app/1.0.0/api/events/type/:type` | Buscar por tipo | `type` |
|
|
61
|
+
| GET | `/events-app/1.0.0/api/events/session/:sessionId` | Buscar por session_id | `sessionId` |
|
|
62
|
+
| GET | `/events-app/1.0.0/api/events/stats` | Estadísticas | - |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 📊 Estructura de la Tabla events_no_finish
|
|
67
|
+
|
|
68
|
+
```sql
|
|
69
|
+
CREATE TABLE events_no_finish (
|
|
70
|
+
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
|
71
|
+
session_header_id bigint(20) unsigned NOT NULL,
|
|
72
|
+
event_type varchar(50) NOT NULL,
|
|
73
|
+
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
|
74
|
+
qty int(11) DEFAULT NULL,
|
|
75
|
+
product_id bigint(20) DEFAULT NULL,
|
|
76
|
+
sku varchar(100) DEFAULT NULL,
|
|
77
|
+
product_name text DEFAULT NULL,
|
|
78
|
+
url varchar(1000) DEFAULT NULL,
|
|
79
|
+
price text DEFAULT NULL,
|
|
80
|
+
old_qty bigint(20) DEFAULT NULL,
|
|
81
|
+
new_qty bigint(20) DEFAULT NULL,
|
|
82
|
+
compressed_data text DEFAULT NULL,
|
|
83
|
+
data_hash varchar(100) DEFAULT NULL,
|
|
84
|
+
event_timestamp timestamp DEFAULT NULL,
|
|
85
|
+
session_id varchar(255) DEFAULT NULL,
|
|
86
|
+
wtf_session varchar(255) DEFAULT NULL,
|
|
87
|
+
site_url varchar(500) DEFAULT NULL,
|
|
88
|
+
PRIMARY KEY (id)
|
|
89
|
+
);
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 🔧 Características Técnicas
|
|
95
|
+
|
|
96
|
+
### 1. Serialización de Datos
|
|
97
|
+
- **BigInt → String**: Los valores `bigint` de MariaDB se convierten automáticamente a string
|
|
98
|
+
- **Date → ISO String**: Las fechas se serializan en formato ISO 8601
|
|
99
|
+
|
|
100
|
+
### 2. Lazy Loading del Modelo
|
|
101
|
+
El modelo se inicializa bajo demanda cuando se realiza la primera consulta:
|
|
102
|
+
```javascript
|
|
103
|
+
async getEventsModel() {
|
|
104
|
+
if (this.eventsModel) return this.eventsModel;
|
|
105
|
+
// Inicialización bajo demanda
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Hot Reload Compatible
|
|
110
|
+
La aplicación es detectada automáticamente por el Hot Reload Manager:
|
|
111
|
+
- Detección de nuevas apps en `apps/{name}/{version}/`
|
|
112
|
+
- Recarga automática de rutas al modificar archivos
|
|
113
|
+
- Watch continuo para cambios futuros
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 📝 Ejemplos de Uso
|
|
118
|
+
|
|
119
|
+
### Listar Eventos
|
|
120
|
+
```bash
|
|
121
|
+
curl -k "https://localhost:9791/events-app/1.0.0/api/events?limit=10"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Respuesta:**
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"success": true,
|
|
128
|
+
"pool": "MySQL-MariaDB",
|
|
129
|
+
"table": "events_no_finish",
|
|
130
|
+
"count": 10,
|
|
131
|
+
"total": 11,
|
|
132
|
+
"data": [
|
|
133
|
+
{
|
|
134
|
+
"id": "17",
|
|
135
|
+
"session_header_id": "12345",
|
|
136
|
+
"event_type": "view_product",
|
|
137
|
+
"created_at": "2026-02-04T23:09:40.000Z",
|
|
138
|
+
"session_id": "30f08519743a83f22ad4bf7b866cda43",
|
|
139
|
+
"product_name": "Producto Ejemplo"
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
"timestamp": "2026-02-17T19:45:00.000Z"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Obtener Evento por ID
|
|
147
|
+
```bash
|
|
148
|
+
curl -k "https://localhost:9791/events-app/1.0.0/api/events/17"
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Buscar por Tipo de Evento
|
|
152
|
+
```bash
|
|
153
|
+
curl -k "https://localhost:9791/events-app/1.0.0/api/events/type/view_product"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Buscar por Session ID
|
|
157
|
+
```bash
|
|
158
|
+
curl -k "https://localhost:9791/events-app/1.0.0/api/events/session/30f08519743a83f22ad4bf7b866cda43"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Obtener Estadísticas
|
|
162
|
+
```bash
|
|
163
|
+
curl -k "https://localhost:9791/events-app/1.0.0/api/events/stats"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Respuesta:**
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"success": true,
|
|
170
|
+
"pool": "MySQL-MariaDB",
|
|
171
|
+
"data": {
|
|
172
|
+
"total": 11,
|
|
173
|
+
"byType": [
|
|
174
|
+
{ "event_type": "view_product", "count": 5 },
|
|
175
|
+
{ "event_type": "add_to_cart", "count": 4 },
|
|
176
|
+
{ "event_type": "remove_from_cart", "count": 2 }
|
|
177
|
+
],
|
|
178
|
+
"bySession": [...]
|
|
179
|
+
},
|
|
180
|
+
"timestamp": "2026-02-17T19:45:00.000Z"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 🎯 UI Web
|
|
187
|
+
|
|
188
|
+
La aplicación incluye una interfaz web accesible en:
|
|
189
|
+
```
|
|
190
|
+
https://localhost:9791/events-app/1.0.0/
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Características de la UI:**
|
|
194
|
+
- Tabla de eventos con paginación
|
|
195
|
+
- Filtros por tipo de evento
|
|
196
|
+
- Búsqueda por session_id
|
|
197
|
+
- Estadísticas en tiempo real
|
|
198
|
+
- Diseño responsive con tema oscuro
|
|
199
|
+
- Actualización automática con botón refresh
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 📦 Manifest (package.json)
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"name": "events-app",
|
|
208
|
+
"version": "1.0.0",
|
|
209
|
+
"description": "Aplicación para consultar eventos no finalizados de otrack_db",
|
|
210
|
+
"author": "BlackCoffee Team",
|
|
211
|
+
"blackcoffee": {
|
|
212
|
+
"displayName": "Events App",
|
|
213
|
+
"entryPoint": "routes/api.json",
|
|
214
|
+
"autoStart": true,
|
|
215
|
+
"minBlackCoffeeVersion": "2.0.0",
|
|
216
|
+
"database": {
|
|
217
|
+
"pool": "MySQL-MariaDB",
|
|
218
|
+
"models": ["EventsModel"]
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## 🔗 URLs de Acceso
|
|
227
|
+
|
|
228
|
+
| Recurso | URL |
|
|
229
|
+
|---------|-----|
|
|
230
|
+
| UI Web | `https://localhost:9791/events-app/1.0.0/` |
|
|
231
|
+
| API Events | `https://localhost:9791/events-app/1.0.0/api/events` |
|
|
232
|
+
| API Stats | `https://localhost:9791/events-app/1.0.0/api/events/stats` |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 🛠️ Desarrollo
|
|
237
|
+
|
|
238
|
+
### Agregar Nuevo Endpoint
|
|
239
|
+
|
|
240
|
+
1. **Agregar método en EventsModel.js:**
|
|
241
|
+
```javascript
|
|
242
|
+
async findByDate(date) {
|
|
243
|
+
const selectSQL = `
|
|
244
|
+
SELECT * FROM ${this.tableName}
|
|
245
|
+
WHERE DATE(created_at) = ?
|
|
246
|
+
ORDER BY id DESC
|
|
247
|
+
`;
|
|
248
|
+
return await this.adapter.query(selectSQL, [date]);
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
2. **Agregar método en EventsController.js:**
|
|
253
|
+
```javascript
|
|
254
|
+
async getEventsByDate(req, res) {
|
|
255
|
+
const model = await this.getEventsModel();
|
|
256
|
+
const date = req.params?.date;
|
|
257
|
+
const events = await model.findByDate(date);
|
|
258
|
+
|
|
259
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
260
|
+
res.end(JSON.stringify({
|
|
261
|
+
success: true,
|
|
262
|
+
count: events.length,
|
|
263
|
+
data: serializeBigInt(events),
|
|
264
|
+
timestamp: new Date().toISOString()
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
3. **Agregar ruta en routes/api.json:**
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"method": "GET",
|
|
273
|
+
"path": "/api/events/date/:date",
|
|
274
|
+
"handler": "getEventsByDate",
|
|
275
|
+
"controller": "controllers/EventsController.js"
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## 📄 Licencia
|
|
282
|
+
|
|
283
|
+
Apache License 2.0 - BlackCoffee Project
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
**Documento creado:** 2026-02-17
|
|
288
|
+
**BlackCoffee:** v2.0.0
|
|
289
|
+
**events-app:** v1.0.0
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Propuesta para Insitu Framework - Binary Upload Support
|
|
2
|
+
|
|
3
|
+
## 📋 Resumen
|
|
4
|
+
|
|
5
|
+
BlackCoffee App Server requiere soporte nativo para **binary uploads** (archivos .tar.gz, imágenes, etc.). Actualmente, Insitu Framework convierte todo el body a string UTF-8, lo que corrompe archivos binarios.
|
|
6
|
+
|
|
7
|
+
## 🐛 Problema Actual
|
|
8
|
+
|
|
9
|
+
En `lib/core/server.js`, línea ~989:
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
// CÓDIGO ACTUAL DE INSITU
|
|
13
|
+
req.body = Buffer.concat(bodyChunks).toString();
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Problema:** `.toString()` convierte el buffer a string UTF-8, corrompiendo datos binarios.
|
|
17
|
+
|
|
18
|
+
**Síntomas:**
|
|
19
|
+
- Archivos .tar.gz llegan corruptos (1720 bytes → 1637 bytes)
|
|
20
|
+
- Magic number gzip (0x1f 0x8b) se pierde
|
|
21
|
+
- Imágenes y otros binarios no se pueden subir
|
|
22
|
+
|
|
23
|
+
## ✅ Solución Propuesta
|
|
24
|
+
|
|
25
|
+
Agregar `req.rawBody` como Buffer **antes** de convertir a string:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
// PROPUESTA PARA INSITU
|
|
29
|
+
const rawBuffer = Buffer.concat(bodyChunks);
|
|
30
|
+
|
|
31
|
+
// Binary Upload Support - BlackCoffee
|
|
32
|
+
req.rawBody = rawBuffer; // ← NUEVO: Body raw como Buffer
|
|
33
|
+
|
|
34
|
+
// Comportamiento original - string para req.body
|
|
35
|
+
req.body = rawBuffer.toString();
|
|
36
|
+
|
|
37
|
+
// Parsear body si es JSON (sin cambios)
|
|
38
|
+
if (this.isJsonRequest(req)) {
|
|
39
|
+
try {
|
|
40
|
+
req.body = JSON.parse(req.body);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
req.body = {};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 📊 Beneficios para Insitu
|
|
48
|
+
|
|
49
|
+
1. **Backward Compatible** - `req.body` sigue funcionando igual
|
|
50
|
+
2. **Binary Upload Support** - `req.rawBody` disponible para archivos
|
|
51
|
+
3. **Sin Breaking Changes** - Todo el código existente sigue funcionando
|
|
52
|
+
4. **Habilita casos de uso avanzados:**
|
|
53
|
+
- Upload de imágenes
|
|
54
|
+
- Upload de archivos .tar.gz
|
|
55
|
+
- Upload de PDFs, documentos
|
|
56
|
+
- Cualquier archivo binario
|
|
57
|
+
|
|
58
|
+
## 🔧 Ubicación del Cambio
|
|
59
|
+
|
|
60
|
+
**Archivo:** `lib/core/server.js`
|
|
61
|
+
**Función:** `handleRequest(req, res)`
|
|
62
|
+
**Línea:** ~989 (dentro de `req.on('end', async () => {...})`)
|
|
63
|
+
|
|
64
|
+
## 📝 Código Completo Propuesto
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
req.on('end', async () => {
|
|
68
|
+
try {
|
|
69
|
+
// Concatenar todos los chunks una sola vez
|
|
70
|
+
const rawBuffer = Buffer.concat(bodyChunks);
|
|
71
|
+
|
|
72
|
+
// ============================================
|
|
73
|
+
// BINARY UPLOAD SUPPORT
|
|
74
|
+
// ============================================
|
|
75
|
+
// Guardar body raw como Buffer para rutas binarias
|
|
76
|
+
// Esto permite uploads de archivos binarios (.tar.gz, imágenes, etc.)
|
|
77
|
+
req.rawBody = rawBuffer;
|
|
78
|
+
// ============================================
|
|
79
|
+
|
|
80
|
+
// Convertir a string para req.body (comportamiento original)
|
|
81
|
+
req.body = rawBuffer.toString();
|
|
82
|
+
|
|
83
|
+
// Actualizar estadísticas globales de bytes recibidos
|
|
84
|
+
StatsHooksHandler.updateRequestBytes(bodySize);
|
|
85
|
+
|
|
86
|
+
// Parsear body si es JSON
|
|
87
|
+
if (this.isJsonRequest(req)) {
|
|
88
|
+
try {
|
|
89
|
+
req.body = JSON.parse(req.body);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
req.body = {};
|
|
92
|
+
|
|
93
|
+
if (hooks) {
|
|
94
|
+
hooks.doAction('request_body_parse_error', req, res, e);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ... resto del código sin cambios ...
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 🧪 Casos de Prueba
|
|
103
|
+
|
|
104
|
+
### 1. JSON Upload (Existente - Sin Cambios)
|
|
105
|
+
```javascript
|
|
106
|
+
// POST /api/users con Content-Type: application/json
|
|
107
|
+
// req.body = { name: "John", email: "john@example.com" }
|
|
108
|
+
// req.rawBody = <Buffer 7b 22 6e 61 6d 65 22 ...>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2. Binary Upload (Nuevo)
|
|
112
|
+
```javascript
|
|
113
|
+
// POST /api/admin/apps/deploy con archivo .tar.gz
|
|
114
|
+
// req.body = " (string corrupto)
|
|
115
|
+
// req.rawBody = <Buffer 1f 8b 08 00 ...> ← Buffer binario correcto
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Multipart Form-Data (Navegador)
|
|
119
|
+
```javascript
|
|
120
|
+
// POST desde <input type="file">
|
|
121
|
+
// Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
|
|
122
|
+
// req.rawBody = <Buffer completo con multipart>
|
|
123
|
+
// req.body = " (string)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 📁 Archivos Modificados en BlackCoffee
|
|
127
|
+
|
|
128
|
+
BlackCoffee ya implementó esta solución en:
|
|
129
|
+
|
|
130
|
+
**Archivo:** `node_modules/insitu-js/lib/core/server.js`
|
|
131
|
+
**Líneas:** 991-1001
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
// Línea 991-1001
|
|
135
|
+
const rawBuffer = Buffer.concat(bodyChunks);
|
|
136
|
+
|
|
137
|
+
// ============================================
|
|
138
|
+
// BINARY UPLOAD SUPPORT - BlackCoffee
|
|
139
|
+
// ============================================
|
|
140
|
+
// Guardar body raw como Buffer para rutas binarias
|
|
141
|
+
// Esto permite uploads de archivos binarios (.tar.gz, imágenes, etc.)
|
|
142
|
+
req.rawBody = rawBuffer;
|
|
143
|
+
// ============================================
|
|
144
|
+
|
|
145
|
+
// Convertir a string para req.body (comportamiento original)
|
|
146
|
+
req.body = rawBuffer.toString();
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## ✅ Estado Actual
|
|
150
|
+
|
|
151
|
+
**BlackCoffee v2.0.0:**
|
|
152
|
+
- ✅ Binary Upload Support implementado
|
|
153
|
+
- ✅ Multipart/form-data parser para uploads desde navegador
|
|
154
|
+
- ✅ Deploy de aplicaciones desde UI Web funcional
|
|
155
|
+
- ✅ req.rawBody disponible en todos los handlers
|
|
156
|
+
|
|
157
|
+
**Insitu Framework v1.3.0:**
|
|
158
|
+
- ✅ Binary Upload Support incorporado en el core
|
|
159
|
+
- ✅ Firewall exception para deploy incorporada
|
|
160
|
+
- ✅ Nuestras propuestas fueron aceptadas e implementadas
|
|
161
|
+
|
|
162
|
+
## 🎉 Propuestas Aceptadas
|
|
163
|
+
|
|
164
|
+
Las siguientes características propuestas por BlackCoffee fueron incorporadas en Insitu Framework v1.3.0:
|
|
165
|
+
|
|
166
|
+
1. **req.rawBody** - Binary Upload Support (línea 997 de `lib/core/server.js`)
|
|
167
|
+
2. **Firewall Exception** - Excepción para `/api/admin/apps/deploy` (líneas 403-406 de `lib/middleware/firewall.js`)
|
|
168
|
+
|
|
169
|
+
**¡Gracias al equipo de Insitu por escuchar a la comunidad!** 🙌
|
|
170
|
+
|
|
171
|
+
## 📞 Contacto
|
|
172
|
+
|
|
173
|
+
**BlackCoffee Team:**
|
|
174
|
+
- Repository: https://gitlab.com/bytedogssyndicate1/bc2
|
|
175
|
+
- Author: Benjamin Sanchez Cardenas
|
|
176
|
+
- Email: bytedogssyndicate@gmail.com
|
|
177
|
+
|
|
178
|
+
**Insitu Framework:**
|
|
179
|
+
- Repository: https://github.com/insitu-framework/insitu-js
|
|
180
|
+
- npm: https://www.npmjs.com/package/insitu-js
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
**Documento creado:** 2026-02-17
|
|
185
|
+
**BlackCoffee:** v2.0.0
|
|
186
|
+
**Insitu Framework:** v1.2.1 (modificado localmente)
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Cambios en Insitu Framework para BlackCoffee
|
|
2
|
+
|
|
3
|
+
## 📋 Resumen
|
|
4
|
+
|
|
5
|
+
BlackCoffee App Server requirió dos modificaciones al core de Insitu Framework para habilitar:
|
|
6
|
+
1. **Binary Upload Support** (req.rawBody)
|
|
7
|
+
2. **Firewall Exception** para deploy de aplicaciones
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🔧 Cambio 1: Binary Upload Support
|
|
12
|
+
|
|
13
|
+
### Archivo: `lib/core/server.js`
|
|
14
|
+
|
|
15
|
+
**Ubicación:** Función `handleRequest(req, res)`, línea ~991
|
|
16
|
+
|
|
17
|
+
### Código Original
|
|
18
|
+
```javascript
|
|
19
|
+
// Línea ~989
|
|
20
|
+
req.body = Buffer.concat(bodyChunks).toString();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Código Modificado
|
|
24
|
+
```javascript
|
|
25
|
+
// Líneas 991-1001
|
|
26
|
+
const rawBuffer = Buffer.concat(bodyChunks);
|
|
27
|
+
|
|
28
|
+
// ============================================
|
|
29
|
+
// BINARY UPLOAD SUPPORT - BlackCoffee
|
|
30
|
+
// ============================================
|
|
31
|
+
// Guardar body raw como Buffer para rutas binarias
|
|
32
|
+
// Esto permite uploads de archivos binarios (.tar.gz, imágenes, etc.)
|
|
33
|
+
req.rawBody = rawBuffer;
|
|
34
|
+
// ============================================
|
|
35
|
+
|
|
36
|
+
// Convertir a string para req.body (comportamiento original)
|
|
37
|
+
req.body = rawBuffer.toString();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Beneficios
|
|
41
|
+
- ✅ Backward compatible - `req.body` sigue funcionando igual
|
|
42
|
+
- ✅ Binary upload support - `req.rawBody` disponible como Buffer
|
|
43
|
+
- ✅ Sin breaking changes - Todo el código existente funciona
|
|
44
|
+
- ✅ Habilita uploads de archivos binarios
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🔧 Cambio 2: Firewall Exception para Deploy
|
|
49
|
+
|
|
50
|
+
### Archivo: `lib/middleware/firewall.js`
|
|
51
|
+
|
|
52
|
+
**Ubicación:** Función `middleware()`, línea 401
|
|
53
|
+
|
|
54
|
+
### Código Original
|
|
55
|
+
```javascript
|
|
56
|
+
// Línea ~401
|
|
57
|
+
middleware() {
|
|
58
|
+
return (req, res, next) => {
|
|
59
|
+
// Disparar hook antes de procesar la solicitud
|
|
60
|
+
const hooks = require('../../index.js').hooks;
|
|
61
|
+
if (hooks) {
|
|
62
|
+
hooks.doAction('firewall_request_received', req, res);
|
|
63
|
+
}
|
|
64
|
+
// ... resto del middleware
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Código Modificado
|
|
68
|
+
```javascript
|
|
69
|
+
// Líneas 401-407
|
|
70
|
+
middleware() {
|
|
71
|
+
return (req, res, next) => {
|
|
72
|
+
// Excluir rutas de administración de deploy
|
|
73
|
+
if (req.method === 'POST' && req.url.startsWith('/api/admin/apps/deploy')) {
|
|
74
|
+
return next(); // Saltar firewall para deploy
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Disparar hook antes de procesar la solicitud
|
|
78
|
+
const hooks = require('../../index.js').hooks;
|
|
79
|
+
if (hooks) {
|
|
80
|
+
hooks.doAction('firewall_request_received', req, res);
|
|
81
|
+
}
|
|
82
|
+
// ... resto del middleware
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Beneficios
|
|
86
|
+
- ✅ Permite deploy de aplicaciones sin desactivar WAF completamente
|
|
87
|
+
- ✅ Excepción específica para `/api/admin/apps/deploy`
|
|
88
|
+
- ✅ El WAF sigue activo para todas las demás rutas
|
|
89
|
+
- ✅ Previene falsos positivos con archivos .tar.gz
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 📊 Estado Actual
|
|
94
|
+
|
|
95
|
+
| Archivo | Estado | Cambios |
|
|
96
|
+
|---------|--------|---------|
|
|
97
|
+
| `lib/core/server.js` | ✅ Modificado | req.rawBody como Buffer |
|
|
98
|
+
| `lib/middleware/firewall.js` | ✅ Modificado | Excepción para deploy |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 🚀 Propuesta para Insitu v1.3.0
|
|
103
|
+
|
|
104
|
+
### 1. Incorporar Binary Upload Support
|
|
105
|
+
|
|
106
|
+
**Ventajas:**
|
|
107
|
+
- Habilita casos de uso de file upload
|
|
108
|
+
- Compatible con todas las apps existentes
|
|
109
|
+
- Sin cambios en la API pública
|
|
110
|
+
|
|
111
|
+
**Implementación Sugerida:**
|
|
112
|
+
```javascript
|
|
113
|
+
// lib/core/server.js, línea ~991
|
|
114
|
+
const rawBuffer = Buffer.concat(bodyChunks);
|
|
115
|
+
|
|
116
|
+
// Binary Upload Support
|
|
117
|
+
req.rawBody = rawBuffer; // ← NUEVO
|
|
118
|
+
|
|
119
|
+
// Comportamiento original
|
|
120
|
+
req.body = rawBuffer.toString();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Incorporar Firewall Exceptions
|
|
124
|
+
|
|
125
|
+
**Ventajas:**
|
|
126
|
+
- Permite configurar rutas excluidas del WAF
|
|
127
|
+
- Útil para uploads de archivos grandes
|
|
128
|
+
- Previene falsos positivos
|
|
129
|
+
|
|
130
|
+
**Implementación Sugerida:**
|
|
131
|
+
```javascript
|
|
132
|
+
// lib/middleware/firewall.js, constructor
|
|
133
|
+
constructor(options = {}) {
|
|
134
|
+
this.excludedRoutes = options.excludedRoutes || [];
|
|
135
|
+
// ... resto del constructor
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// lib/middleware/firewall.js, middleware()
|
|
139
|
+
middleware() {
|
|
140
|
+
return (req, res, next) => {
|
|
141
|
+
// Verificar rutas excluidas
|
|
142
|
+
if (this.excludedRoutes.some(route => req.url.startsWith(route))) {
|
|
143
|
+
return next();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ... resto del middleware
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Configuración:**
|
|
152
|
+
```javascript
|
|
153
|
+
const firewall = new Firewall({
|
|
154
|
+
excludedRoutes: ['/api/admin/apps/deploy']
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 📁 Archivos de Referencia
|
|
161
|
+
|
|
162
|
+
BlackCoffee mantiene estos cambios en:
|
|
163
|
+
- `node_modules/insitu-js/lib/core/server.js`
|
|
164
|
+
- `node_modules/insitu-js/lib/middleware/firewall.js`
|
|
165
|
+
|
|
166
|
+
**Documentación completa en:**
|
|
167
|
+
- `docs/INSITU_BINARY_UPLOAD_PROPOSAL.md` - Propuesta detallada
|
|
168
|
+
- `docs/INSITU_FIREWALL_EXCEPTION.md` - Este archivo
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 📞 Contacto
|
|
173
|
+
|
|
174
|
+
**BlackCoffee Team:**
|
|
175
|
+
- Repository: https://gitlab.com/bytedogssyndicate1/bc2
|
|
176
|
+
- Author: Benjamin Sanchez Cardenas
|
|
177
|
+
- Email: bytedogssyndicate@gmail.com
|
|
178
|
+
|
|
179
|
+
**Insitu Framework:**
|
|
180
|
+
- Repository: https://github.com/insitu-framework/insitu-js
|
|
181
|
+
- npm: https://www.npmjs.com/package/insitu-js
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
**Documento creado:** 2026-02-17
|
|
186
|
+
**BlackCoffee:** v2.0.0
|
|
187
|
+
**Insitu Framework:** v1.2.1 (modificado localmente)
|