@arela/uploader 1.0.24 → 1.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/docs/AUTO_PROCESSING_PIPELINE.md +258 -0
- package/docs/COMPLETE_USAGE_GUIDE.md +1363 -0
- package/docs/DATABASESERVICE_IMPROVEMENTS.md +546 -0
- package/docs/PASO_2_TEST_RESULTS.md +298 -0
- package/docs/PASO_3_PLAN.md +385 -0
- package/docs/PHASE_1_FILE_DETECTION.md +366 -0
- package/docs/PHASE_2_API_INTEGRATION.md +426 -0
- package/docs/PHASE_3_DATABASE_MANAGEMENT.md +480 -0
- package/docs/PHASE_4_FILE_OPERATIONS.md +448 -0
- package/docs/PHASE_5_WATCH_MODE.md +450 -0
- package/docs/PHASE_6_SIGNAL_HANDLING.md +472 -0
- package/docs/PHASE_7_ADVANCED_FEATURES.md +560 -0
- package/docs/PLAN_WATCH_FEATURE.md +417 -0
- package/docs/README.md +480 -0
- package/docs/SCHEMA_ALIGNMENT_SUMMARY.md +301 -0
- package/docs/SMARTWATCH_DATABASE_REFACTORING.md +181 -0
- package/docs/SMART_WATCH_DATABASE_CHANGES.md +502 -0
- package/docs/TESTING_WATCH_MODE.md +212 -0
- package/docs/WATCHER_API_IMPLEMENTATION.md +520 -0
- package/docs/WATCHER_API_INTEGRATION.md +562 -0
- package/docs/WATCHER_SETUP_GUIDE.md +614 -0
- package/docs/WATCH_ARCHITECTURE.md +395 -0
- package/docs/WATCH_AUTO_PIPELINE.md +334 -0
- package/docs/WATCH_CONFIGURATION.md +267 -0
- package/docs/WATCH_USAGE_GUIDE.md +567 -0
- package/docs/commands.md +14 -0
- package/package.json +1 -1
- package/src/commands/IdentifyCommand.js +8 -0
- package/src/config/config.js +2 -2
- package/src/file-detection.js +42 -1
- package/src/scoring/scoring-engine.js +35 -7
- package/.vscode/settings.json +0 -1
- package/coverage/IdentifyCommand.js.html +0 -1462
- package/coverage/PropagateCommand.js.html +0 -1507
- package/coverage/PushCommand.js.html +0 -1504
- package/coverage/ScanCommand.js.html +0 -1654
- package/coverage/UploadCommand.js.html +0 -1846
- package/coverage/WatchCommand.js.html +0 -4111
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -191
- package/coverage/lcov-report/IdentifyCommand.js.html +0 -1462
- package/coverage/lcov-report/PropagateCommand.js.html +0 -1507
- package/coverage/lcov-report/PushCommand.js.html +0 -1504
- package/coverage/lcov-report/ScanCommand.js.html +0 -1654
- package/coverage/lcov-report/UploadCommand.js.html +0 -1846
- package/coverage/lcov-report/WatchCommand.js.html +0 -4111
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -191
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -210
- package/coverage/lcov.info +0 -1937
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/docs/API_ENDPOINTS_FOR_DETECTION.md +0 -647
- package/docs/API_RETRY_MECHANISM.md +0 -338
- package/docs/ARELA_IDENTIFY_IMPLEMENTATION.md +0 -489
- package/docs/ARELA_IDENTIFY_QUICKREF.md +0 -186
- package/docs/ARELA_PROPAGATE_IMPLEMENTATION.md +0 -581
- package/docs/ARELA_PROPAGATE_QUICKREF.md +0 -272
- package/docs/ARELA_PUSH_IMPLEMENTATION.md +0 -577
- package/docs/ARELA_PUSH_QUICKREF.md +0 -322
- package/docs/ARELA_SCAN_IMPLEMENTATION.md +0 -373
- package/docs/ARELA_SCAN_QUICKREF.md +0 -139
- package/docs/CROSS_PLATFORM_PATH_HANDLING.md +0 -597
- package/docs/DETECTION_ATTEMPT_TRACKING.md +0 -414
- package/docs/MIGRATION_UPLOADER_TO_FILE_STATS.md +0 -1020
- package/docs/MULTI_LEVEL_DIRECTORY_SCANNING.md +0 -494
- package/docs/QUICK_REFERENCE_API_DETECTION.md +0 -264
- package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +0 -200
- package/docs/STATS_COMMAND_SEQUENCE_DIAGRAM.md +0 -287
- package/docs/STATS_COMMAND_SIMPLE.md +0 -93
|
@@ -0,0 +1,1363 @@
|
|
|
1
|
+
# 📘 Complete Usage Guide - ARELA-UPLOADER v1.0
|
|
2
|
+
|
|
3
|
+
Este es un manual comprensivo que muestra cómo usar todas las características de ARELA-UPLOADER en escenarios reales.
|
|
4
|
+
|
|
5
|
+
## Tabla de Contenidos
|
|
6
|
+
|
|
7
|
+
1. [Instalación y Configuración](#instalación-y-configuración)
|
|
8
|
+
2. [Conceptos Básicos](#conceptos-básicos)
|
|
9
|
+
3. [Guías por Fase](#guías-por-fase)
|
|
10
|
+
4. [Casos de Uso Prácticos](#casos-de-uso-prácticos)
|
|
11
|
+
5. [Ejemplos Avanzados](#ejemplos-avanzados)
|
|
12
|
+
6. [Solución de Problemas](#solución-de-problemas)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Instalación y Configuración
|
|
17
|
+
|
|
18
|
+
### Requisitos Previos
|
|
19
|
+
- Node.js v14+
|
|
20
|
+
- npm o yarn
|
|
21
|
+
- Base de datos PostgreSQL (opcional, para persistencia)
|
|
22
|
+
- Cuenta Supabase (para uploads a la nube)
|
|
23
|
+
|
|
24
|
+
### Instalación
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Clonar repositorio
|
|
28
|
+
git clone https://github.com/inspiraCode/arela-uploader.git
|
|
29
|
+
cd arela-uploader
|
|
30
|
+
|
|
31
|
+
# Instalar dependencias
|
|
32
|
+
npm install
|
|
33
|
+
|
|
34
|
+
# Configurar variables de entorno
|
|
35
|
+
cp .env.example .env
|
|
36
|
+
|
|
37
|
+
# Editar archivo .env con tus credenciales
|
|
38
|
+
# SUPABASE_URL=https://...
|
|
39
|
+
# SUPABASE_ANON_KEY=...
|
|
40
|
+
# DB_HOST=localhost
|
|
41
|
+
# DB_USER=postgres
|
|
42
|
+
# etc.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Estructura de Directorios
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
arela-uploader/
|
|
49
|
+
├── src/
|
|
50
|
+
│ ├── commands/ (Comandos CLI)
|
|
51
|
+
│ ├── services/ (Lógica de negocio)
|
|
52
|
+
│ ├── utils/ (Utilidades)
|
|
53
|
+
│ ├── errors/ (Manejo de errores)
|
|
54
|
+
│ ├── config/ (Configuración)
|
|
55
|
+
│ └── index.js (Punto de entrada)
|
|
56
|
+
├── tests/ (Suite de tests)
|
|
57
|
+
├── docs/ (Documentación)
|
|
58
|
+
├── logs/ (Logs de ejecución)
|
|
59
|
+
├── uploads/ (Directorio de uploads)
|
|
60
|
+
└── package.json
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Conceptos Básicos
|
|
66
|
+
|
|
67
|
+
### 1. Sessions (Sesiones)
|
|
68
|
+
Una sesión representa una serie de uploads. Rastrea el progreso, estado y metadatos.
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
// Una sesión contiene:
|
|
72
|
+
{
|
|
73
|
+
id: 'session-uuid',
|
|
74
|
+
userId: 'user-123',
|
|
75
|
+
status: 'active', // active, paused, completed, error
|
|
76
|
+
fileCount: 10,
|
|
77
|
+
successCount: 8,
|
|
78
|
+
errorCount: 2,
|
|
79
|
+
startTime: '2025-11-14T10:30:00Z',
|
|
80
|
+
endTime: null,
|
|
81
|
+
totalSize: 52428800, // en bytes
|
|
82
|
+
metadata: { ... }
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Uploads
|
|
87
|
+
Cada archivo subido es un upload en la sesión.
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
// Un upload contiene:
|
|
91
|
+
{
|
|
92
|
+
id: 'upload-uuid',
|
|
93
|
+
sessionId: 'session-uuid',
|
|
94
|
+
fileName: 'document.pdf',
|
|
95
|
+
fileSize: 2048000,
|
|
96
|
+
status: 'completed', // pending, uploading, completed, failed
|
|
97
|
+
uploadedUrl: 'https://...',
|
|
98
|
+
attempts: 1,
|
|
99
|
+
startTime: '2025-11-14T10:30:00Z',
|
|
100
|
+
endTime: '2025-11-14T10:30:02Z'
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 3. Events (Eventos)
|
|
105
|
+
Los eventos registran actividades importantes durante una sesión.
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
// Un evento contiene:
|
|
109
|
+
{
|
|
110
|
+
id: 'event-uuid',
|
|
111
|
+
sessionId: 'session-uuid',
|
|
112
|
+
eventType: 'upload', // upload, error, warning, info
|
|
113
|
+
message: 'Archivo uploadado exitosamente',
|
|
114
|
+
details: { fileName: 'document.pdf', size: 2048000 },
|
|
115
|
+
timestamp: '2025-11-14T10:30:02Z'
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Guías por Fase
|
|
122
|
+
|
|
123
|
+
### Phase 1: File Detection & Validation
|
|
124
|
+
|
|
125
|
+
**¿Qué hace?** Detecta y valida archivos antes de procesarlos.
|
|
126
|
+
|
|
127
|
+
#### Ejemplo 1: Validar un Archivo
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
const FileDetection = require('./src/file-detection');
|
|
131
|
+
|
|
132
|
+
async function validateFile() {
|
|
133
|
+
const result = FileDetection.validateFile('/path/to/document.pdf');
|
|
134
|
+
|
|
135
|
+
if (result.isValid) {
|
|
136
|
+
console.log('✅ Archivo válido:', result.file.name);
|
|
137
|
+
console.log(' Tamaño:', result.file.size / 1024, 'KB');
|
|
138
|
+
console.log(' Tipo:', result.file.mimeType);
|
|
139
|
+
} else {
|
|
140
|
+
console.log('❌ Archivo inválido:');
|
|
141
|
+
result.errors.forEach(err => console.log(' -', err));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
validateFile();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Ejemplo 2: Detectar Archivos en Directorio
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
const FileDetection = require('./src/file-detection');
|
|
152
|
+
|
|
153
|
+
async function detectFiles() {
|
|
154
|
+
const files = FileDetection.detectFilesInDirectory('/Users/documents');
|
|
155
|
+
|
|
156
|
+
console.log(`📁 Encontrados ${files.length} archivos:\n`);
|
|
157
|
+
|
|
158
|
+
files.forEach(file => {
|
|
159
|
+
console.log(` 📄 ${file.name}`);
|
|
160
|
+
console.log(` Tipo: ${file.type}`);
|
|
161
|
+
console.log(` Tamaño: ${file.size} bytes\n`);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
detectFiles();
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### Ejemplo 3: Procesar Archivos con Sanitización
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
const FileDetection = require('./src/file-detection');
|
|
172
|
+
const FileSanitizer = require('./src/utils/FileSanitizer');
|
|
173
|
+
|
|
174
|
+
async function processFiles() {
|
|
175
|
+
const files = FileDetection.detectFilesInDirectory('/uploads');
|
|
176
|
+
|
|
177
|
+
const processed = files.map(file => ({
|
|
178
|
+
original: file.name,
|
|
179
|
+
sanitized: FileSanitizer.sanitizeFileName(file.name),
|
|
180
|
+
valid: FileDetection.validateFile(file.path).isValid
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
console.log('📋 Archivos procesados:');
|
|
184
|
+
processed.forEach(p => {
|
|
185
|
+
console.log(`\n Original: ${p.original}`);
|
|
186
|
+
console.log(` Sanitizado: ${p.sanitized}`);
|
|
187
|
+
console.log(` Válido: ${p.valid ? '✅' : '❌'}`);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
processFiles();
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Phase 2: API Service Integration
|
|
197
|
+
|
|
198
|
+
**¿Qué hace?** Integra con servicios API para subir archivos a la nube.
|
|
199
|
+
|
|
200
|
+
#### Ejemplo 1: Upload Básico
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
204
|
+
|
|
205
|
+
async function uploadFile() {
|
|
206
|
+
try {
|
|
207
|
+
// Crear servicio
|
|
208
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
209
|
+
|
|
210
|
+
// Autenticar
|
|
211
|
+
console.log('🔐 Autenticando...');
|
|
212
|
+
await uploader.authenticate();
|
|
213
|
+
console.log('✅ Autenticado');
|
|
214
|
+
|
|
215
|
+
// Subir archivo
|
|
216
|
+
console.log('⬆️ Subiendo archivo...');
|
|
217
|
+
const result = await uploader.uploadFile('/path/to/file.pdf', {
|
|
218
|
+
bucket: 'documents',
|
|
219
|
+
public: false
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
console.log('✅ Upload completado');
|
|
223
|
+
console.log(' URL:', result.url);
|
|
224
|
+
console.log(' Tamaño:', result.size, 'bytes');
|
|
225
|
+
|
|
226
|
+
return result;
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error('❌ Error:', error.message);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
uploadFile();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### Ejemplo 2: Upload con Reintentos
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
239
|
+
|
|
240
|
+
async function uploadWithRetry() {
|
|
241
|
+
try {
|
|
242
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
243
|
+
await uploader.authenticate();
|
|
244
|
+
|
|
245
|
+
console.log('⬆️ Intentando upload con reintentos...');
|
|
246
|
+
|
|
247
|
+
const result = await uploader.uploadFileWithRetry(
|
|
248
|
+
'/path/to/file.pdf',
|
|
249
|
+
{ bucket: 'documents', public: false },
|
|
250
|
+
5 // máximo 5 intentos
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
console.log('✅ Éxito después de', result.metadata.attempts, 'intento(s)');
|
|
254
|
+
return result;
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('❌ Falló después de reintentos:', error.message);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
uploadWithRetry();
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
#### Ejemplo 3: Upload Múltiple
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
267
|
+
|
|
268
|
+
async function uploadMultiple() {
|
|
269
|
+
const files = [
|
|
270
|
+
'/path/to/file1.pdf',
|
|
271
|
+
'/path/to/file2.pdf',
|
|
272
|
+
'/path/to/file3.pdf'
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
277
|
+
await uploader.authenticate();
|
|
278
|
+
|
|
279
|
+
console.log(`⬆️ Subiendo ${files.length} archivos...`);
|
|
280
|
+
|
|
281
|
+
const results = await Promise.all(
|
|
282
|
+
files.map(file =>
|
|
283
|
+
uploader.uploadFile(file, {
|
|
284
|
+
bucket: 'documents',
|
|
285
|
+
public: false
|
|
286
|
+
})
|
|
287
|
+
)
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const successful = results.filter(r => r.success).length;
|
|
291
|
+
console.log(`✅ ${successful}/${files.length} archivos subidos`);
|
|
292
|
+
|
|
293
|
+
return results;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.error('❌ Error:', error.message);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
uploadMultiple();
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
### Phase 3: Database Management
|
|
305
|
+
|
|
306
|
+
**¿Qué hace?** Gestiona persistencia de datos en base de datos.
|
|
307
|
+
|
|
308
|
+
#### Ejemplo 1: Crear y Gestionar Sesión
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
312
|
+
|
|
313
|
+
async function manageSession() {
|
|
314
|
+
const db = new DatabaseService();
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
// Conectar
|
|
318
|
+
console.log('🔌 Conectando a BD...');
|
|
319
|
+
await db.connect();
|
|
320
|
+
console.log('✅ Conectado');
|
|
321
|
+
|
|
322
|
+
// Crear sesión
|
|
323
|
+
console.log('📝 Creando sesión...');
|
|
324
|
+
const session = await db.createSession({
|
|
325
|
+
userId: 'user-123',
|
|
326
|
+
status: 'active',
|
|
327
|
+
startTime: new Date()
|
|
328
|
+
});
|
|
329
|
+
console.log('✅ Sesión creada:', session.id);
|
|
330
|
+
|
|
331
|
+
// Actualizar sesión
|
|
332
|
+
await db.updateSession(session.id, {
|
|
333
|
+
fileCount: 5
|
|
334
|
+
});
|
|
335
|
+
console.log('✅ Sesión actualizada');
|
|
336
|
+
|
|
337
|
+
// Desconectar
|
|
338
|
+
await db.disconnect();
|
|
339
|
+
console.log('✅ Desconectado');
|
|
340
|
+
|
|
341
|
+
} catch (error) {
|
|
342
|
+
console.error('❌ Error:', error.message);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
manageSession();
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Ejemplo 2: Registrar Uploads
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
353
|
+
const FileDetection = require('./src/file-detection');
|
|
354
|
+
|
|
355
|
+
async function registerUploads() {
|
|
356
|
+
const db = new DatabaseService();
|
|
357
|
+
|
|
358
|
+
try {
|
|
359
|
+
await db.connect();
|
|
360
|
+
|
|
361
|
+
// Crear sesión
|
|
362
|
+
const session = await db.createSession({
|
|
363
|
+
userId: 'user-123',
|
|
364
|
+
status: 'active',
|
|
365
|
+
startTime: new Date()
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Registrar archivos
|
|
369
|
+
const files = ['/file1.pdf', '/file2.pdf'];
|
|
370
|
+
|
|
371
|
+
for (const filePath of files) {
|
|
372
|
+
const file = FileDetection.detectFile(filePath);
|
|
373
|
+
|
|
374
|
+
const upload = await db.saveUpload({
|
|
375
|
+
sessionId: session.id,
|
|
376
|
+
filePath: file.path,
|
|
377
|
+
fileName: file.name,
|
|
378
|
+
fileSize: file.size,
|
|
379
|
+
mimeType: file.mimeType,
|
|
380
|
+
status: 'completed',
|
|
381
|
+
uploadedUrl: `https://bucket.storage/...`,
|
|
382
|
+
startTime: new Date(),
|
|
383
|
+
endTime: new Date()
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
console.log(`✅ Registrado: ${file.name}`);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
await db.disconnect();
|
|
390
|
+
} catch (error) {
|
|
391
|
+
console.error('❌ Error:', error.message);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
registerUploads();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### Ejemplo 3: Obtener Estadísticas de Sesión
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
402
|
+
|
|
403
|
+
async function getStatistics() {
|
|
404
|
+
const db = new DatabaseService();
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
await db.connect();
|
|
408
|
+
|
|
409
|
+
// Obtener sesión
|
|
410
|
+
const session = await db.getSession('session-id');
|
|
411
|
+
console.log('📊 Sesión:', session.id);
|
|
412
|
+
console.log(' Estado:', session.status);
|
|
413
|
+
console.log(' Archivos:', session.fileCount);
|
|
414
|
+
console.log(' Exitosos:', session.successCount);
|
|
415
|
+
console.log(' Errores:', session.errorCount);
|
|
416
|
+
console.log(' Tamaño total:', session.totalSize / 1024 / 1024, 'MB');
|
|
417
|
+
|
|
418
|
+
// Obtener uploads
|
|
419
|
+
const uploads = await db.getUploads('session-id');
|
|
420
|
+
console.log('\n📁 Uploads:');
|
|
421
|
+
uploads.forEach(upload => {
|
|
422
|
+
console.log(` - ${upload.fileName} (${upload.status})`);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// Obtener eventos
|
|
426
|
+
const events = await db.getEvents('session-id');
|
|
427
|
+
console.log('\n📝 Eventos:', events.length);
|
|
428
|
+
|
|
429
|
+
await db.disconnect();
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.error('❌ Error:', error.message);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
getStatistics();
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
### Phase 4: File Operations & Logging
|
|
441
|
+
|
|
442
|
+
**¿Qué hace?** Proporciona operaciones seguras de archivos y logging completo.
|
|
443
|
+
|
|
444
|
+
#### Ejemplo 1: Operaciones de Archivo
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
const FileOperations = require('./src/utils/FileOperations');
|
|
448
|
+
|
|
449
|
+
async function fileOperations() {
|
|
450
|
+
try {
|
|
451
|
+
// Crear archivo
|
|
452
|
+
await FileOperations.createFile(
|
|
453
|
+
'/path/to/output.txt',
|
|
454
|
+
'Contenido del archivo'
|
|
455
|
+
);
|
|
456
|
+
console.log('✅ Archivo creado');
|
|
457
|
+
|
|
458
|
+
// Leer archivo
|
|
459
|
+
const content = await FileOperations.readFile('/path/to/output.txt');
|
|
460
|
+
console.log('📖 Contenido:', content);
|
|
461
|
+
|
|
462
|
+
// Copiar archivo
|
|
463
|
+
await FileOperations.copyFile(
|
|
464
|
+
'/path/to/output.txt',
|
|
465
|
+
'/path/to/backup.txt'
|
|
466
|
+
);
|
|
467
|
+
console.log('📋 Archivo copiado');
|
|
468
|
+
|
|
469
|
+
// Obtener información
|
|
470
|
+
const stats = await FileOperations.getFileStats('/path/to/output.txt');
|
|
471
|
+
console.log('📊 Tamaño:', stats.size, 'bytes');
|
|
472
|
+
console.log('📅 Modificado:', stats.mtime);
|
|
473
|
+
|
|
474
|
+
// Eliminar archivo
|
|
475
|
+
await FileOperations.deleteFile('/path/to/backup.txt');
|
|
476
|
+
console.log('🗑️ Archivo eliminado');
|
|
477
|
+
|
|
478
|
+
} catch (error) {
|
|
479
|
+
console.error('❌ Error:', error.message);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
fileOperations();
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
#### Ejemplo 2: Sistema de Logging
|
|
487
|
+
|
|
488
|
+
```javascript
|
|
489
|
+
const LoggingService = require('./src/services/LoggingService');
|
|
490
|
+
|
|
491
|
+
function logging() {
|
|
492
|
+
const logger = LoggingService.getInstance();
|
|
493
|
+
|
|
494
|
+
// Diferentes niveles
|
|
495
|
+
logger.trace('Información muy detallada');
|
|
496
|
+
logger.debug('Información de debug');
|
|
497
|
+
logger.info('Información general');
|
|
498
|
+
logger.warn('Advertencia importante');
|
|
499
|
+
logger.error('Error ocurrido');
|
|
500
|
+
|
|
501
|
+
// Log con contexto
|
|
502
|
+
logger.info('Upload iniciado', {
|
|
503
|
+
fileName: 'document.pdf',
|
|
504
|
+
size: 2048000,
|
|
505
|
+
sessionId: 'session-123'
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
// Log de error con stack
|
|
509
|
+
try {
|
|
510
|
+
throw new Error('Algo salió mal');
|
|
511
|
+
} catch (error) {
|
|
512
|
+
logger.error('Error en operación', error);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
console.log('✅ Logs registrados en:', logger.getLogFile());
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
logging();
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
### Phase 5: Watch Mode & Sessions
|
|
524
|
+
|
|
525
|
+
**¿Qué hace?** Monitorea directorios y procesa archivos automáticamente.
|
|
526
|
+
|
|
527
|
+
#### Ejemplo 1: Modo Vigilancia Básico
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
# Iniciar vigilancia de directorio
|
|
531
|
+
node -e "
|
|
532
|
+
const WatchCommand = require('./src/commands/WatchCommand');
|
|
533
|
+
|
|
534
|
+
(async () => {
|
|
535
|
+
const watch = new WatchCommand();
|
|
536
|
+
await watch.execute({
|
|
537
|
+
watchDir: '/Users/documents/uploads',
|
|
538
|
+
sessionName: 'main-session',
|
|
539
|
+
batchSize: 10,
|
|
540
|
+
debounceTime: 2000
|
|
541
|
+
});
|
|
542
|
+
})();
|
|
543
|
+
"
|
|
544
|
+
|
|
545
|
+
# La sesión continúa hasta Ctrl+C
|
|
546
|
+
# Cada archivo detectado se procesa automáticamente
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
#### Ejemplo 2: Vigilancia con Filtros
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
const WatchCommand = require('./src/commands/WatchCommand');
|
|
553
|
+
|
|
554
|
+
async function watchWithFilters() {
|
|
555
|
+
const watch = new WatchCommand();
|
|
556
|
+
|
|
557
|
+
await watch.execute({
|
|
558
|
+
watchDir: '/uploads',
|
|
559
|
+
sessionName: 'pdf-session',
|
|
560
|
+
recursive: true,
|
|
561
|
+
batchSize: 5,
|
|
562
|
+
debounceTime: 1000,
|
|
563
|
+
fileFilter: ['.pdf', '.doc', '.docx'],
|
|
564
|
+
excludePatterns: ['*.tmp', '.DS_Store']
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
watchWithFilters();
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
#### Ejemplo 3: Gestión Manual de Sesiones
|
|
572
|
+
|
|
573
|
+
```javascript
|
|
574
|
+
const SessionManager = require('./src/services/SessionManager');
|
|
575
|
+
|
|
576
|
+
async function manageSessions() {
|
|
577
|
+
try {
|
|
578
|
+
// Crear sesión
|
|
579
|
+
const session = await SessionManager.createSession({
|
|
580
|
+
name: 'Manual Upload Session',
|
|
581
|
+
userId: 'user-123',
|
|
582
|
+
description: 'Uploading documents'
|
|
583
|
+
});
|
|
584
|
+
console.log('✅ Sesión creada:', session.id);
|
|
585
|
+
|
|
586
|
+
// Realizar operaciones...
|
|
587
|
+
|
|
588
|
+
// Pausar sesión
|
|
589
|
+
await SessionManager.pauseSession(session.id);
|
|
590
|
+
console.log('⏸️ Sesión pausada');
|
|
591
|
+
|
|
592
|
+
// Reanudar
|
|
593
|
+
await SessionManager.resumeSession(session.id);
|
|
594
|
+
console.log('▶️ Sesión reanudada');
|
|
595
|
+
|
|
596
|
+
// Completar
|
|
597
|
+
await SessionManager.completeSession(session.id);
|
|
598
|
+
console.log('✅ Sesión completada');
|
|
599
|
+
|
|
600
|
+
} catch (error) {
|
|
601
|
+
console.error('❌ Error:', error.message);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
manageSessions();
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
### Phase 6: Signal Handling & Graceful Shutdown
|
|
611
|
+
|
|
612
|
+
**¿Qué hace?** Maneja señales del sistema para apagado elegante.
|
|
613
|
+
|
|
614
|
+
#### Ejemplo 1: Setup Básico de Señales
|
|
615
|
+
|
|
616
|
+
```javascript
|
|
617
|
+
const SignalHandler = require('./src/services/SignalHandler');
|
|
618
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
619
|
+
|
|
620
|
+
async function setupSignalHandling() {
|
|
621
|
+
const signalHandler = SignalHandler.getInstance();
|
|
622
|
+
const db = new DatabaseService();
|
|
623
|
+
|
|
624
|
+
// Conectar a BD
|
|
625
|
+
await db.connect();
|
|
626
|
+
|
|
627
|
+
// Registrar cleanup de BD
|
|
628
|
+
signalHandler.registerCleanup('database', async () => {
|
|
629
|
+
console.log('🗄️ Cerrando conexión a BD...');
|
|
630
|
+
await db.disconnect();
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
// Registrar handler de SIGINT (Ctrl+C)
|
|
634
|
+
signalHandler.on('SIGINT', async () => {
|
|
635
|
+
console.log('\n✋ Apagado iniciado');
|
|
636
|
+
await signalHandler.shutdown('SIGINT');
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// Setup
|
|
640
|
+
signalHandler.setup();
|
|
641
|
+
|
|
642
|
+
console.log('✅ Signal handling configurado');
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
setupSignalHandling();
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
#### Ejemplo 2: Apagado Elegante Completo
|
|
649
|
+
|
|
650
|
+
```javascript
|
|
651
|
+
const SignalHandler = require('./src/services/SignalHandler');
|
|
652
|
+
const CleanupManager = require('./src/services/CleanupManager');
|
|
653
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
654
|
+
|
|
655
|
+
async function gracefulShutdown() {
|
|
656
|
+
const signalHandler = SignalHandler.getInstance();
|
|
657
|
+
const cleanupManager = new CleanupManager();
|
|
658
|
+
const db = new DatabaseService();
|
|
659
|
+
|
|
660
|
+
await db.connect();
|
|
661
|
+
|
|
662
|
+
// Registrar tareas de limpieza (orden LIFO)
|
|
663
|
+
cleanupManager.register('sessions', async () => {
|
|
664
|
+
console.log('💾 Guardando sesiones activas...');
|
|
665
|
+
// guardar sesiones
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
cleanupManager.register('uploads', async () => {
|
|
669
|
+
console.log('⬆️ Finalizando uploads...');
|
|
670
|
+
// finalizar uploads
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
cleanupManager.register('database', async () => {
|
|
674
|
+
console.log('🗄️ Cerrando BD...');
|
|
675
|
+
await db.disconnect();
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
// Manejar señales
|
|
679
|
+
signalHandler.on('SIGINT', async () => {
|
|
680
|
+
console.log('\n⏹️ Apagado elegante iniciado...');
|
|
681
|
+
console.log('Ejecutando limpieza en orden...\n');
|
|
682
|
+
|
|
683
|
+
await cleanupManager.cleanup();
|
|
684
|
+
|
|
685
|
+
console.log('\n✅ Apagado completado');
|
|
686
|
+
process.exit(0);
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
signalHandler.setup();
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
gracefulShutdown();
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
### Phase 7: Advanced Features & Integration
|
|
698
|
+
|
|
699
|
+
**¿Qué hace?** Proporciona análisis, reportes y monitoreo avanzado.
|
|
700
|
+
|
|
701
|
+
#### Ejemplo 1: Filtrado Avanzado
|
|
702
|
+
|
|
703
|
+
```javascript
|
|
704
|
+
const AdvancedFilterService = require('./src/services/AdvancedFilterService');
|
|
705
|
+
|
|
706
|
+
async function advancedFiltering() {
|
|
707
|
+
const filterService = new AdvancedFilterService();
|
|
708
|
+
|
|
709
|
+
const files = [
|
|
710
|
+
'/file1.pdf',
|
|
711
|
+
'/file2.doc',
|
|
712
|
+
'/file3.pdf',
|
|
713
|
+
'/file4.xlsx'
|
|
714
|
+
];
|
|
715
|
+
|
|
716
|
+
// Filtrar por múltiples criterios
|
|
717
|
+
const filtered = filterService.filterFiles(files, {
|
|
718
|
+
extensions: ['.pdf'],
|
|
719
|
+
minSize: 1024,
|
|
720
|
+
maxSize: 50 * 1024 * 1024,
|
|
721
|
+
dateRange: {
|
|
722
|
+
from: new Date('2025-11-01'),
|
|
723
|
+
to: new Date('2025-11-14')
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
console.log('📋 Resultados del filtrado:');
|
|
728
|
+
console.log(' Original:', files.length);
|
|
729
|
+
console.log(' Filtrado:', filtered.length);
|
|
730
|
+
|
|
731
|
+
// Usar presets
|
|
732
|
+
const pdfsOnly = filterService.applyPreset(files, 'pdfOnly');
|
|
733
|
+
console.log(' PDFs solo:', pdfsOnly.length);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
advancedFiltering();
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
#### Ejemplo 2: Generación de Reportes
|
|
740
|
+
|
|
741
|
+
```javascript
|
|
742
|
+
const ReportingService = require('./src/services/ReportingService');
|
|
743
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
744
|
+
|
|
745
|
+
async function generateReports() {
|
|
746
|
+
const db = new DatabaseService();
|
|
747
|
+
const reportingService = new ReportingService();
|
|
748
|
+
|
|
749
|
+
await db.connect();
|
|
750
|
+
|
|
751
|
+
// Obtener sesión
|
|
752
|
+
const session = await db.getSession('session-id');
|
|
753
|
+
|
|
754
|
+
// Generar reporte de sesión
|
|
755
|
+
const sessionReport = reportingService.generateSessionReport(session);
|
|
756
|
+
console.log('📊 Reporte de Sesión:');
|
|
757
|
+
console.log(' Archivos:', sessionReport.summary.totalUploads);
|
|
758
|
+
console.log(' Exitosos:', sessionReport.summary.successCount);
|
|
759
|
+
console.log(' Errores:', sessionReport.summary.errorCount);
|
|
760
|
+
|
|
761
|
+
// Exportar a JSON
|
|
762
|
+
await reportingService.exportReportJson(
|
|
763
|
+
sessionReport,
|
|
764
|
+
'./reports/session-report.json'
|
|
765
|
+
);
|
|
766
|
+
console.log('💾 Reporte guardado en JSON');
|
|
767
|
+
|
|
768
|
+
// Exportar a CSV
|
|
769
|
+
await reportingService.exportReportCsv(
|
|
770
|
+
sessionReport,
|
|
771
|
+
'./reports/session-report.csv'
|
|
772
|
+
);
|
|
773
|
+
console.log('💾 Reporte guardado en CSV');
|
|
774
|
+
|
|
775
|
+
await db.disconnect();
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
generateReports();
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
#### Ejemplo 3: Benchmarking de Rendimiento
|
|
782
|
+
|
|
783
|
+
```javascript
|
|
784
|
+
const BenchmarkingService = require('./src/services/BenchmarkingService');
|
|
785
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
786
|
+
|
|
787
|
+
async function benchmarkPerformance() {
|
|
788
|
+
const benchmark = new BenchmarkingService();
|
|
789
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
790
|
+
|
|
791
|
+
await uploader.authenticate();
|
|
792
|
+
|
|
793
|
+
// Iniciar benchmark
|
|
794
|
+
const bench = benchmark.startBenchmark('upload-test');
|
|
795
|
+
|
|
796
|
+
// Marcar puntos
|
|
797
|
+
benchmark.mark(bench, 'validation-complete');
|
|
798
|
+
|
|
799
|
+
// Ejecutar upload
|
|
800
|
+
await uploader.uploadFile('/path/to/file.pdf');
|
|
801
|
+
benchmark.mark(bench, 'upload-complete');
|
|
802
|
+
|
|
803
|
+
// Completar
|
|
804
|
+
const result = benchmark.completeBenchmark(bench);
|
|
805
|
+
|
|
806
|
+
console.log('⏱️ Resultados del Benchmark:');
|
|
807
|
+
console.log(' Duración:', result.duration, 'ms');
|
|
808
|
+
console.log(' Memoria:', result.memory, 'bytes');
|
|
809
|
+
|
|
810
|
+
// Generar reporte
|
|
811
|
+
const report = benchmark.generateBenchmarkReport();
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
benchmarkPerformance();
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### Ejemplo 4: Monitoreo en Tiempo Real
|
|
818
|
+
|
|
819
|
+
```javascript
|
|
820
|
+
const MonitoringService = require('./src/services/MonitoringService');
|
|
821
|
+
|
|
822
|
+
async function setupMonitoring() {
|
|
823
|
+
const monitor = new MonitoringService();
|
|
824
|
+
|
|
825
|
+
// Agregar reglas de alerta
|
|
826
|
+
monitor.addAlertRule({
|
|
827
|
+
name: 'high-memory',
|
|
828
|
+
type: 'memory',
|
|
829
|
+
operator: 'greaterThan',
|
|
830
|
+
threshold: 500,
|
|
831
|
+
severity: 'warning'
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
// Suscribirse a alertas
|
|
835
|
+
monitor.subscribe('critical', (alert) => {
|
|
836
|
+
console.error('🔴 CRÍTICA:', alert.message);
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
monitor.subscribe('warning', (alert) => {
|
|
840
|
+
console.warn('🟡 ADVERTENCIA:', alert.message);
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
// Actualizar métricas
|
|
844
|
+
setInterval(() => {
|
|
845
|
+
monitor.updateMetrics({
|
|
846
|
+
cpu: Math.random() * 100,
|
|
847
|
+
memory: Math.random() * 600,
|
|
848
|
+
disk: Math.random() * 100,
|
|
849
|
+
connections: Math.floor(Math.random() * 50),
|
|
850
|
+
errorRate: Math.random() * 0.1
|
|
851
|
+
});
|
|
852
|
+
}, 5000);
|
|
853
|
+
|
|
854
|
+
console.log('✅ Monitoreo iniciado');
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
setupMonitoring();
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
---
|
|
861
|
+
|
|
862
|
+
## Casos de Uso Prácticos
|
|
863
|
+
|
|
864
|
+
### Caso 1: Workflow Completo (Upload Simple)
|
|
865
|
+
|
|
866
|
+
```javascript
|
|
867
|
+
const FileDetection = require('./src/file-detection');
|
|
868
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
869
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
870
|
+
const LoggingService = require('./src/services/LoggingService');
|
|
871
|
+
|
|
872
|
+
async function completeWorkflow(filePath) {
|
|
873
|
+
const logger = LoggingService.getInstance();
|
|
874
|
+
const db = new DatabaseService();
|
|
875
|
+
|
|
876
|
+
try {
|
|
877
|
+
logger.info('=== INICIANDO WORKFLOW COMPLETO ===');
|
|
878
|
+
|
|
879
|
+
// STEP 1: Validar archivo
|
|
880
|
+
logger.info('📋 STEP 1: Validando archivo...');
|
|
881
|
+
const validation = FileDetection.validateFile(filePath);
|
|
882
|
+
|
|
883
|
+
if (!validation.isValid) {
|
|
884
|
+
throw new Error('Archivo inválido: ' + validation.errors.join(', '));
|
|
885
|
+
}
|
|
886
|
+
logger.info('✅ Archivo válido');
|
|
887
|
+
|
|
888
|
+
// STEP 2: Conectar BD
|
|
889
|
+
logger.info('🔌 STEP 2: Conectando BD...');
|
|
890
|
+
await db.connect();
|
|
891
|
+
logger.info('✅ Conectado');
|
|
892
|
+
|
|
893
|
+
// STEP 3: Crear sesión
|
|
894
|
+
logger.info('📝 STEP 3: Creando sesión...');
|
|
895
|
+
const session = await db.createSession({
|
|
896
|
+
userId: 'user-123',
|
|
897
|
+
status: 'active',
|
|
898
|
+
startTime: new Date()
|
|
899
|
+
});
|
|
900
|
+
logger.info('✅ Sesión creada: ' + session.id);
|
|
901
|
+
|
|
902
|
+
// STEP 4: Autenticar con proveedor
|
|
903
|
+
logger.info('🔐 STEP 4: Autenticando con Supabase...');
|
|
904
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
905
|
+
await uploader.authenticate();
|
|
906
|
+
logger.info('✅ Autenticado');
|
|
907
|
+
|
|
908
|
+
// STEP 5: Subir archivo
|
|
909
|
+
logger.info('⬆️ STEP 5: Subiendo archivo...');
|
|
910
|
+
const uploadResult = await uploader.uploadFile(filePath);
|
|
911
|
+
logger.info('✅ Subido a: ' + uploadResult.url);
|
|
912
|
+
|
|
913
|
+
// STEP 6: Registrar en BD
|
|
914
|
+
logger.info('📝 STEP 6: Registrando en BD...');
|
|
915
|
+
const file = FileDetection.detectFile(filePath);
|
|
916
|
+
const upload = await db.saveUpload({
|
|
917
|
+
sessionId: session.id,
|
|
918
|
+
filePath: file.path,
|
|
919
|
+
fileName: file.name,
|
|
920
|
+
fileSize: file.size,
|
|
921
|
+
mimeType: file.mimeType,
|
|
922
|
+
status: 'completed',
|
|
923
|
+
uploadedUrl: uploadResult.url,
|
|
924
|
+
startTime: new Date(),
|
|
925
|
+
endTime: new Date()
|
|
926
|
+
});
|
|
927
|
+
logger.info('✅ Registrado en BD');
|
|
928
|
+
|
|
929
|
+
// STEP 7: Actualizar sesión
|
|
930
|
+
logger.info('🔄 STEP 7: Actualizando sesión...');
|
|
931
|
+
await db.updateSession(session.id, {
|
|
932
|
+
status: 'completed',
|
|
933
|
+
successCount: 1,
|
|
934
|
+
fileCount: 1,
|
|
935
|
+
endTime: new Date()
|
|
936
|
+
});
|
|
937
|
+
logger.info('✅ Sesión actualizada');
|
|
938
|
+
|
|
939
|
+
await db.disconnect();
|
|
940
|
+
|
|
941
|
+
logger.info('=== WORKFLOW COMPLETADO CON ÉXITO ===\n');
|
|
942
|
+
|
|
943
|
+
return {
|
|
944
|
+
session,
|
|
945
|
+
upload,
|
|
946
|
+
uploadResult
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
} catch (error) {
|
|
950
|
+
logger.error('ERROR EN WORKFLOW', error);
|
|
951
|
+
await db.disconnect();
|
|
952
|
+
throw error;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// Uso
|
|
957
|
+
completeWorkflow('/path/to/document.pdf')
|
|
958
|
+
.then(result => console.log('✅ Resultado:', result))
|
|
959
|
+
.catch(error => console.error('❌ Error:', error.message));
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
### Caso 2: Vigilancia Continua con Reportes
|
|
963
|
+
|
|
964
|
+
```javascript
|
|
965
|
+
const WatchCommand = require('./src/commands/WatchCommand');
|
|
966
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
967
|
+
const ReportingService = require('./src/services/ReportingService');
|
|
968
|
+
const LoggingService = require('./src/services/LoggingService');
|
|
969
|
+
|
|
970
|
+
async function continuousWatchWithReports() {
|
|
971
|
+
const logger = LoggingService.getInstance();
|
|
972
|
+
const db = new DatabaseService();
|
|
973
|
+
const reportingService = new ReportingService();
|
|
974
|
+
|
|
975
|
+
try {
|
|
976
|
+
await db.connect();
|
|
977
|
+
|
|
978
|
+
// Crear sesión de vigilancia
|
|
979
|
+
const session = await db.createSession({
|
|
980
|
+
userId: 'system',
|
|
981
|
+
status: 'active',
|
|
982
|
+
startTime: new Date()
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
logger.info('🚀 Iniciando vigilancia continua');
|
|
986
|
+
|
|
987
|
+
// Iniciar vigilancia
|
|
988
|
+
const watch = new WatchCommand();
|
|
989
|
+
await watch.execute({
|
|
990
|
+
watchDir: '/uploads',
|
|
991
|
+
sessionName: 'continuous-watch-' + Date.now(),
|
|
992
|
+
batchSize: 10,
|
|
993
|
+
debounceTime: 2000
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
// Generar reportes cada 1 hora
|
|
997
|
+
setInterval(async () => {
|
|
998
|
+
const updatedSession = await db.getSession(session.id);
|
|
999
|
+
const report = reportingService.generateSessionReport(updatedSession);
|
|
1000
|
+
|
|
1001
|
+
logger.info('📊 REPORTE PERIÓDICO', {
|
|
1002
|
+
totalUploads: report.summary.totalUploads,
|
|
1003
|
+
successCount: report.summary.successCount,
|
|
1004
|
+
errorCount: report.summary.errorCount
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
await reportingService.exportReportJson(
|
|
1008
|
+
report,
|
|
1009
|
+
`./reports/periodic-${Date.now()}.json`
|
|
1010
|
+
);
|
|
1011
|
+
}, 60 * 60 * 1000); // Cada hora
|
|
1012
|
+
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
logger.error('Error en vigilancia continua', error);
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
continuousWatchWithReports();
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
### Caso 3: Procesamiento por Lotes con Monitoreo
|
|
1022
|
+
|
|
1023
|
+
```javascript
|
|
1024
|
+
const BatchProcessor = require('./src/services/BatchProcessor');
|
|
1025
|
+
const MonitoringService = require('./src/services/MonitoringService');
|
|
1026
|
+
const LoggingService = require('./src/services/LoggingService');
|
|
1027
|
+
|
|
1028
|
+
async function processWithMonitoring(files) {
|
|
1029
|
+
const logger = LoggingService.getInstance();
|
|
1030
|
+
const processor = new BatchProcessor({ batchSize: 10 });
|
|
1031
|
+
const monitor = new MonitoringService();
|
|
1032
|
+
|
|
1033
|
+
// Configurar alertas
|
|
1034
|
+
monitor.addAlertRule({
|
|
1035
|
+
name: 'high-error-rate',
|
|
1036
|
+
type: 'errorRate',
|
|
1037
|
+
operator: 'greaterThan',
|
|
1038
|
+
threshold: 0.2,
|
|
1039
|
+
severity: 'critical'
|
|
1040
|
+
});
|
|
1041
|
+
|
|
1042
|
+
// Suscribirse a alertas
|
|
1043
|
+
monitor.subscribe('critical', (alert) => {
|
|
1044
|
+
logger.error('🔴 ALERTA:', alert.message);
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
// Procesar archivos
|
|
1048
|
+
for (const file of files) {
|
|
1049
|
+
processor.addFile(file);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
const results = await processor.processBatch();
|
|
1053
|
+
|
|
1054
|
+
// Actualizar métricas
|
|
1055
|
+
const successful = results.filter(r => r.success).length;
|
|
1056
|
+
const errorRate = (results.length - successful) / results.length;
|
|
1057
|
+
|
|
1058
|
+
monitor.updateMetrics({
|
|
1059
|
+
errorRate,
|
|
1060
|
+
connections: 5,
|
|
1061
|
+
memory: 256,
|
|
1062
|
+
cpu: 45,
|
|
1063
|
+
disk: 65
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
// Generar reporte
|
|
1067
|
+
const health = monitor.getHealthStatus();
|
|
1068
|
+
logger.info('📊 Estado del Sistema:', health);
|
|
1069
|
+
|
|
1070
|
+
return results;
|
|
1071
|
+
}
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
---
|
|
1075
|
+
|
|
1076
|
+
## Ejemplos Avanzados
|
|
1077
|
+
|
|
1078
|
+
### Integración Completa con Todas las Fases
|
|
1079
|
+
|
|
1080
|
+
```javascript
|
|
1081
|
+
const FileDetection = require('./src/file-detection');
|
|
1082
|
+
const UploadServiceFactory = require('./src/services/upload/UploadServiceFactory');
|
|
1083
|
+
const DatabaseService = require('./src/services/DatabaseService');
|
|
1084
|
+
const LoggingService = require('./src/services/LoggingService');
|
|
1085
|
+
const SignalHandler = require('./src/services/SignalHandler');
|
|
1086
|
+
const AdvancedFilterService = require('./src/services/AdvancedFilterService');
|
|
1087
|
+
const ReportingService = require('./src/services/ReportingService');
|
|
1088
|
+
const BenchmarkingService = require('./src/services/BenchmarkingService');
|
|
1089
|
+
const MonitoringService = require('./src/services/MonitoringService');
|
|
1090
|
+
|
|
1091
|
+
async function fullIntegration(dirPath, userId) {
|
|
1092
|
+
const logger = LoggingService.getInstance();
|
|
1093
|
+
const db = new DatabaseService();
|
|
1094
|
+
const signalHandler = SignalHandler.getInstance();
|
|
1095
|
+
|
|
1096
|
+
try {
|
|
1097
|
+
logger.info('🚀 INICIANDO INTEGRACIÓN COMPLETA');
|
|
1098
|
+
|
|
1099
|
+
// Setup signal handling
|
|
1100
|
+
signalHandler.registerCleanup('database', async () => {
|
|
1101
|
+
await db.disconnect();
|
|
1102
|
+
});
|
|
1103
|
+
signalHandler.setup();
|
|
1104
|
+
|
|
1105
|
+
// Conectar BD
|
|
1106
|
+
await db.connect();
|
|
1107
|
+
|
|
1108
|
+
// Crear sesión
|
|
1109
|
+
const session = await db.createSession({
|
|
1110
|
+
userId,
|
|
1111
|
+
status: 'active',
|
|
1112
|
+
startTime: new Date()
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
// Detectar archivos
|
|
1116
|
+
const files = FileDetection.detectFilesInDirectory(dirPath);
|
|
1117
|
+
|
|
1118
|
+
// Filtrado avanzado
|
|
1119
|
+
const filterService = new AdvancedFilterService();
|
|
1120
|
+
const filtered = filterService.filterFiles(files.map(f => f.path), {
|
|
1121
|
+
extensions: ['.pdf', '.doc', '.docx'],
|
|
1122
|
+
maxSize: 50 * 1024 * 1024
|
|
1123
|
+
});
|
|
1124
|
+
|
|
1125
|
+
// Benchmarking
|
|
1126
|
+
const benchmark = new BenchmarkingService();
|
|
1127
|
+
const bench = benchmark.startBenchmark('full-workflow');
|
|
1128
|
+
|
|
1129
|
+
// Upload con monitoreo
|
|
1130
|
+
const uploader = UploadServiceFactory.createUploadService('supabase');
|
|
1131
|
+
await uploader.authenticate();
|
|
1132
|
+
|
|
1133
|
+
const monitor = new MonitoringService();
|
|
1134
|
+
monitor.addAlertRule({
|
|
1135
|
+
name: 'upload-failures',
|
|
1136
|
+
type: 'errorRate',
|
|
1137
|
+
operator: 'greaterThan',
|
|
1138
|
+
threshold: 0.1,
|
|
1139
|
+
severity: 'critical'
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
const uploadResults = [];
|
|
1143
|
+
let successful = 0;
|
|
1144
|
+
let failed = 0;
|
|
1145
|
+
|
|
1146
|
+
for (const filePath of filtered) {
|
|
1147
|
+
try {
|
|
1148
|
+
const result = await uploader.uploadFile(filePath, {
|
|
1149
|
+
bucket: 'documents',
|
|
1150
|
+
public: false
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
const file = FileDetection.detectFile(filePath);
|
|
1154
|
+
const upload = await db.saveUpload({
|
|
1155
|
+
sessionId: session.id,
|
|
1156
|
+
filePath: file.path,
|
|
1157
|
+
fileName: file.name,
|
|
1158
|
+
fileSize: file.size,
|
|
1159
|
+
mimeType: file.mimeType,
|
|
1160
|
+
status: 'completed',
|
|
1161
|
+
uploadedUrl: result.url,
|
|
1162
|
+
startTime: new Date(),
|
|
1163
|
+
endTime: new Date()
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1166
|
+
uploadResults.push(upload);
|
|
1167
|
+
successful++;
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
failed++;
|
|
1170
|
+
logger.error('Error uploadando archivo', { error: error.message });
|
|
1171
|
+
|
|
1172
|
+
await db.saveEvent({
|
|
1173
|
+
sessionId: session.id,
|
|
1174
|
+
eventType: 'error',
|
|
1175
|
+
message: 'Error uploadando archivo',
|
|
1176
|
+
details: { error: error.message }
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
// Completar benchmark
|
|
1182
|
+
benchmark.mark(bench, 'uploads-complete');
|
|
1183
|
+
const benchResult = benchmark.completeBenchmark(bench);
|
|
1184
|
+
|
|
1185
|
+
// Actualizar sesión
|
|
1186
|
+
await db.updateSession(session.id, {
|
|
1187
|
+
status: 'completed',
|
|
1188
|
+
successCount: successful,
|
|
1189
|
+
errorCount: failed,
|
|
1190
|
+
fileCount: successful + failed,
|
|
1191
|
+
endTime: new Date()
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
// Generar reportes
|
|
1195
|
+
const reportingService = new ReportingService();
|
|
1196
|
+
const updatedSession = await db.getSession(session.id);
|
|
1197
|
+
const report = reportingService.generateSessionReport(updatedSession);
|
|
1198
|
+
|
|
1199
|
+
await reportingService.exportReportJson(
|
|
1200
|
+
report,
|
|
1201
|
+
`./reports/full-workflow-${Date.now()}.json`
|
|
1202
|
+
);
|
|
1203
|
+
|
|
1204
|
+
// Monitoreo final
|
|
1205
|
+
monitor.updateMetrics({
|
|
1206
|
+
errorRate: failed / (successful + failed),
|
|
1207
|
+
memory: process.memoryUsage().heapUsed,
|
|
1208
|
+
cpu: 0
|
|
1209
|
+
});
|
|
1210
|
+
|
|
1211
|
+
const health = monitor.getHealthStatus();
|
|
1212
|
+
|
|
1213
|
+
logger.info('✅ INTEGRACIÓN COMPLETADA', {
|
|
1214
|
+
filesDetected: files.length,
|
|
1215
|
+
filesFiltered: filtered.length,
|
|
1216
|
+
filesUploaded: successful,
|
|
1217
|
+
filesFailed: failed,
|
|
1218
|
+
duration: benchResult.duration,
|
|
1219
|
+
health: health.status
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
await db.disconnect();
|
|
1223
|
+
|
|
1224
|
+
return {
|
|
1225
|
+
session,
|
|
1226
|
+
uploadResults,
|
|
1227
|
+
report,
|
|
1228
|
+
benchmark: benchResult,
|
|
1229
|
+
health
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
} catch (error) {
|
|
1233
|
+
logger.error('ERROR EN INTEGRACIÓN COMPLETA', error);
|
|
1234
|
+
await db.disconnect();
|
|
1235
|
+
throw error;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// Uso
|
|
1240
|
+
fullIntegration('/uploads', 'user-123')
|
|
1241
|
+
.then(result => console.log('✅ Éxito:', result))
|
|
1242
|
+
.catch(error => console.error('❌ Error:', error.message));
|
|
1243
|
+
```
|
|
1244
|
+
|
|
1245
|
+
---
|
|
1246
|
+
|
|
1247
|
+
## Solución de Problemas
|
|
1248
|
+
|
|
1249
|
+
### Problema: "ECONNREFUSED" en BD
|
|
1250
|
+
|
|
1251
|
+
**Síntoma:** Error de conexión a base de datos
|
|
1252
|
+
|
|
1253
|
+
**Solución:**
|
|
1254
|
+
```bash
|
|
1255
|
+
# Verificar que PostgreSQL está corriendo
|
|
1256
|
+
psql --version
|
|
1257
|
+
|
|
1258
|
+
# Verificar variables de entorno
|
|
1259
|
+
echo $DB_HOST
|
|
1260
|
+
echo $DB_PORT
|
|
1261
|
+
echo $DB_NAME
|
|
1262
|
+
|
|
1263
|
+
# Verificar credenciales
|
|
1264
|
+
psql -h localhost -U postgres
|
|
1265
|
+
```
|
|
1266
|
+
|
|
1267
|
+
### Problema: "Authentication Failed" con Supabase
|
|
1268
|
+
|
|
1269
|
+
**Síntoma:** Error de autenticación con API
|
|
1270
|
+
|
|
1271
|
+
**Solución:**
|
|
1272
|
+
```bash
|
|
1273
|
+
# Verificar variables de entorno
|
|
1274
|
+
echo $SUPABASE_URL
|
|
1275
|
+
echo $SUPABASE_ANON_KEY
|
|
1276
|
+
|
|
1277
|
+
# Verificar credenciales en Supabase console
|
|
1278
|
+
# Generar nuevas claves si es necesario
|
|
1279
|
+
|
|
1280
|
+
# Probar conexión
|
|
1281
|
+
curl -H "Authorization: Bearer $SUPABASE_ANON_KEY" $SUPABASE_URL
|
|
1282
|
+
```
|
|
1283
|
+
|
|
1284
|
+
### Problema: Archivos no se detectan en vigilancia
|
|
1285
|
+
|
|
1286
|
+
**Síntoma:** WatchCommand no procesa archivos nuevos
|
|
1287
|
+
|
|
1288
|
+
**Solución:**
|
|
1289
|
+
```javascript
|
|
1290
|
+
// Aumentar debounceTime
|
|
1291
|
+
await watch.execute({
|
|
1292
|
+
watchDir: '/uploads',
|
|
1293
|
+
sessionName: 'debug-session',
|
|
1294
|
+
debounceTime: 5000 // Aumentar a 5 segundos
|
|
1295
|
+
});
|
|
1296
|
+
|
|
1297
|
+
// Verificar permisos de lectura
|
|
1298
|
+
ls -la /uploads
|
|
1299
|
+
|
|
1300
|
+
// Verificar logs
|
|
1301
|
+
tail -f logs/app-*.log
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
### Problema: Memoria alta durante uploads
|
|
1305
|
+
|
|
1306
|
+
**Síntoma:** Aplicación usa mucha memoria
|
|
1307
|
+
|
|
1308
|
+
**Solución:**
|
|
1309
|
+
```javascript
|
|
1310
|
+
// Reducir tamaño de lote
|
|
1311
|
+
const batch = new BatchProcessor({ batchSize: 5 });
|
|
1312
|
+
|
|
1313
|
+
// Procesar de a uno
|
|
1314
|
+
for (const file of files) {
|
|
1315
|
+
await uploader.uploadFile(file);
|
|
1316
|
+
// Dar tiempo para garbage collection
|
|
1317
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1318
|
+
}
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
---
|
|
1322
|
+
|
|
1323
|
+
## Resumen de Comandos Útiles
|
|
1324
|
+
|
|
1325
|
+
```bash
|
|
1326
|
+
# Validar archivo específico
|
|
1327
|
+
node -e "
|
|
1328
|
+
const FileDetection = require('./src/file-detection');
|
|
1329
|
+
console.log(FileDetection.validateFile('/path/to/file.pdf'));
|
|
1330
|
+
"
|
|
1331
|
+
|
|
1332
|
+
# Iniciar vigilancia
|
|
1333
|
+
npm run watch -- --dir /uploads
|
|
1334
|
+
|
|
1335
|
+
# Generar reportes
|
|
1336
|
+
npm run report -- --session-id session-uuid
|
|
1337
|
+
|
|
1338
|
+
# Ejecutar tests
|
|
1339
|
+
npm test
|
|
1340
|
+
|
|
1341
|
+
# Ver logs en tiempo real
|
|
1342
|
+
tail -f logs/app-$(date +%Y-%m-%d).log
|
|
1343
|
+
|
|
1344
|
+
# Cleanup de logs antiguos
|
|
1345
|
+
npm run cleanup-logs -- --days 30
|
|
1346
|
+
```
|
|
1347
|
+
|
|
1348
|
+
---
|
|
1349
|
+
|
|
1350
|
+
## Documentación Adicional
|
|
1351
|
+
|
|
1352
|
+
- [Phase 1: File Detection](./PHASE_1_FILE_DETECTION.md)
|
|
1353
|
+
- [Phase 2: API Integration](./PHASE_2_API_INTEGRATION.md)
|
|
1354
|
+
- [Phase 3: Database](./PHASE_3_DATABASE_MANAGEMENT.md)
|
|
1355
|
+
- [Phase 4: File Operations](./PHASE_4_FILE_OPERATIONS.md)
|
|
1356
|
+
- [Phase 5: Watch Mode](./PHASE_5_WATCH_MODE.md)
|
|
1357
|
+
- [Phase 6: Signal Handling](./PHASE_6_SIGNAL_HANDLING.md)
|
|
1358
|
+
- [Phase 7: Advanced Features](./PHASE_7_ADVANCED_FEATURES.md)
|
|
1359
|
+
|
|
1360
|
+
---
|
|
1361
|
+
|
|
1362
|
+
**ARELA-UPLOADER v1.0** | Documentación Completa | Noviembre 2025
|
|
1363
|
+
|