@arela/uploader 1.0.24 → 1.1.1

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 (80) hide show
  1. package/docs/AUTO_PROCESSING_PIPELINE.md +258 -0
  2. package/docs/COMPLETE_USAGE_GUIDE.md +1363 -0
  3. package/docs/DATABASESERVICE_IMPROVEMENTS.md +546 -0
  4. package/docs/PASO_2_TEST_RESULTS.md +298 -0
  5. package/docs/PASO_3_PLAN.md +385 -0
  6. package/docs/PHASE_1_FILE_DETECTION.md +366 -0
  7. package/docs/PHASE_2_API_INTEGRATION.md +426 -0
  8. package/docs/PHASE_3_DATABASE_MANAGEMENT.md +480 -0
  9. package/docs/PHASE_4_FILE_OPERATIONS.md +448 -0
  10. package/docs/PHASE_5_WATCH_MODE.md +450 -0
  11. package/docs/PHASE_6_SIGNAL_HANDLING.md +472 -0
  12. package/docs/PHASE_7_ADVANCED_FEATURES.md +560 -0
  13. package/docs/PLAN_WATCH_FEATURE.md +417 -0
  14. package/docs/README.md +480 -0
  15. package/docs/SCHEMA_ALIGNMENT_SUMMARY.md +301 -0
  16. package/docs/SMARTWATCH_DATABASE_REFACTORING.md +181 -0
  17. package/docs/SMART_WATCH_DATABASE_CHANGES.md +502 -0
  18. package/docs/TESTING_WATCH_MODE.md +212 -0
  19. package/docs/WATCHER_API_IMPLEMENTATION.md +520 -0
  20. package/docs/WATCHER_API_INTEGRATION.md +562 -0
  21. package/docs/WATCHER_SETUP_GUIDE.md +614 -0
  22. package/docs/WATCH_ARCHITECTURE.md +395 -0
  23. package/docs/WATCH_AUTO_PIPELINE.md +334 -0
  24. package/docs/WATCH_CONFIGURATION.md +267 -0
  25. package/docs/WATCH_USAGE_GUIDE.md +567 -0
  26. package/docs/commands.md +14 -0
  27. package/package.json +1 -1
  28. package/src/commands/IdentifyCommand.js +11 -0
  29. package/src/config/config.js +2 -2
  30. package/src/file-detection.js +42 -1
  31. package/src/scoring/scoring-engine.js +40 -7
  32. package/src/services/LoggingService.js +5 -3
  33. package/.vscode/settings.json +0 -1
  34. package/coverage/IdentifyCommand.js.html +0 -1462
  35. package/coverage/PropagateCommand.js.html +0 -1507
  36. package/coverage/PushCommand.js.html +0 -1504
  37. package/coverage/ScanCommand.js.html +0 -1654
  38. package/coverage/UploadCommand.js.html +0 -1846
  39. package/coverage/WatchCommand.js.html +0 -4111
  40. package/coverage/base.css +0 -224
  41. package/coverage/block-navigation.js +0 -87
  42. package/coverage/favicon.png +0 -0
  43. package/coverage/index.html +0 -191
  44. package/coverage/lcov-report/IdentifyCommand.js.html +0 -1462
  45. package/coverage/lcov-report/PropagateCommand.js.html +0 -1507
  46. package/coverage/lcov-report/PushCommand.js.html +0 -1504
  47. package/coverage/lcov-report/ScanCommand.js.html +0 -1654
  48. package/coverage/lcov-report/UploadCommand.js.html +0 -1846
  49. package/coverage/lcov-report/WatchCommand.js.html +0 -4111
  50. package/coverage/lcov-report/base.css +0 -224
  51. package/coverage/lcov-report/block-navigation.js +0 -87
  52. package/coverage/lcov-report/favicon.png +0 -0
  53. package/coverage/lcov-report/index.html +0 -191
  54. package/coverage/lcov-report/prettify.css +0 -1
  55. package/coverage/lcov-report/prettify.js +0 -2
  56. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  57. package/coverage/lcov-report/sorter.js +0 -210
  58. package/coverage/lcov.info +0 -1937
  59. package/coverage/prettify.css +0 -1
  60. package/coverage/prettify.js +0 -2
  61. package/coverage/sort-arrow-sprite.png +0 -0
  62. package/coverage/sorter.js +0 -210
  63. package/docs/API_ENDPOINTS_FOR_DETECTION.md +0 -647
  64. package/docs/API_RETRY_MECHANISM.md +0 -338
  65. package/docs/ARELA_IDENTIFY_IMPLEMENTATION.md +0 -489
  66. package/docs/ARELA_IDENTIFY_QUICKREF.md +0 -186
  67. package/docs/ARELA_PROPAGATE_IMPLEMENTATION.md +0 -581
  68. package/docs/ARELA_PROPAGATE_QUICKREF.md +0 -272
  69. package/docs/ARELA_PUSH_IMPLEMENTATION.md +0 -577
  70. package/docs/ARELA_PUSH_QUICKREF.md +0 -322
  71. package/docs/ARELA_SCAN_IMPLEMENTATION.md +0 -373
  72. package/docs/ARELA_SCAN_QUICKREF.md +0 -139
  73. package/docs/CROSS_PLATFORM_PATH_HANDLING.md +0 -597
  74. package/docs/DETECTION_ATTEMPT_TRACKING.md +0 -414
  75. package/docs/MIGRATION_UPLOADER_TO_FILE_STATS.md +0 -1020
  76. package/docs/MULTI_LEVEL_DIRECTORY_SCANNING.md +0 -494
  77. package/docs/QUICK_REFERENCE_API_DETECTION.md +0 -264
  78. package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +0 -200
  79. package/docs/STATS_COMMAND_SEQUENCE_DIAGRAM.md +0 -287
  80. package/docs/STATS_COMMAND_SIMPLE.md +0 -93
@@ -0,0 +1,614 @@
1
+ # 🚀 Guía Paso a Paso: Integrar Watcher con arela-api
2
+
3
+ ## 📌 Objetivo Final
4
+ Permitir que el frontend monitoree el estado del watcher en tiempo real a través de endpoints REST en la arela-api.
5
+
6
+ ---
7
+
8
+ ## ✅ Pasos de Implementación
9
+
10
+ ### **Paso 1: Preparar arela-uploader para exportar WatchService**
11
+
12
+ #### 1.1 Crear archivo de exportaciones
13
+
14
+ Crear: `src/services/index.js`
15
+
16
+ ```javascript
17
+ // Exportar todos los servicios disponibles públicamente
18
+ export { default as watchService } from './WatchService.js';
19
+ export { default as databaseService } from './DatabaseService.js';
20
+ export { default as autoProcessingService } from './AutoProcessingService.js';
21
+ export { default as logger } from './LoggingService.js';
22
+ ```
23
+
24
+ #### 1.2 Actualizar package.json de arela-uploader
25
+
26
+ Agregar campo `exports`:
27
+
28
+ ```json
29
+ {
30
+ "name": "arela-uploader",
31
+ "version": "1.0.0",
32
+ "type": "module",
33
+ "exports": {
34
+ ".": "./src/index.js",
35
+ "./services": "./src/services/index.js",
36
+ "./commands": "./src/commands/index.js"
37
+ },
38
+ "main": "./src/index.js"
39
+ }
40
+ ```
41
+
42
+ ✅ **Resultado:** Otros módulos pueden hacer:
43
+ ```javascript
44
+ import { watchService } from 'arela-uploader/services';
45
+ ```
46
+
47
+ ---
48
+
49
+ ### **Paso 2: Preparar arela-api para usar WatchService**
50
+
51
+ #### 2.1 Instalar dependencia de arela-uploader
52
+
53
+ En el directorio `arela-api`:
54
+
55
+ ```bash
56
+ # Opción A: Instalar desde ruta local
57
+ npm install ../arela-uploader
58
+
59
+ # Opción B: Si está publicado en npm
60
+ npm install arela-uploader
61
+ ```
62
+
63
+ #### 2.2 Crear carpeta de rutas si no existe
64
+
65
+ ```bash
66
+ mkdir -p src/routes
67
+ ```
68
+
69
+ #### 2.3 Crear archivo de rutas del watcher
70
+
71
+ Crear: `arela-api/src/routes/watcher.routes.js`
72
+
73
+ **Copiar contenido completo del archivo en `WATCHER_API_IMPLEMENTATION.md`**
74
+
75
+ ```javascript
76
+ import express from 'express';
77
+ import logger from '../services/LoggingService.js';
78
+
79
+ const router = express.Router();
80
+
81
+ export function initWatcherRoutes(app, watchService) {
82
+ // ... copiar todos los endpoints de WATCHER_API_IMPLEMENTATION.md ...
83
+ }
84
+
85
+ export default router;
86
+ ```
87
+
88
+ #### 2.4 Integrar rutas en app.js
89
+
90
+ En `arela-api/src/app.js`:
91
+
92
+ ```javascript
93
+ import express from 'express';
94
+ import { initWatcherRoutes } from './routes/watcher.routes.js';
95
+ import { watchService } from 'arela-uploader/services'; // ✨ Nuevo
96
+
97
+ const app = express();
98
+
99
+ // Middleware
100
+ app.use(express.json());
101
+ app.use(express.urlencoded({ extended: true }));
102
+
103
+ // ... otras rutas ...
104
+
105
+ // ✨ Inicializar rutas del watcher
106
+ initWatcherRoutes(app, watchService);
107
+
108
+ // Error handling
109
+ app.use((err, req, res, next) => {
110
+ console.error(err);
111
+ res.status(500).json({
112
+ error: 'Internal server error',
113
+ message: err.message,
114
+ });
115
+ });
116
+
117
+ export default app;
118
+ ```
119
+
120
+ ---
121
+
122
+ ### **Paso 3: Agregar Autenticación (Opcional pero Recomendado)**
123
+
124
+ #### 3.1 Crear middleware de autenticación
125
+
126
+ Crear: `arela-api/src/middleware/auth.js`
127
+
128
+ ```javascript
129
+ import jwt from 'jsonwebtoken';
130
+
131
+ export const verifyAuth = (req, res, next) => {
132
+ try {
133
+ const token = req.headers.authorization?.split(' ')[1];
134
+
135
+ if (!token) {
136
+ return res.status(401).json({ error: 'No token provided' });
137
+ }
138
+
139
+ const decoded = jwt.verify(token, process.env.JWT_SECRET);
140
+ req.user = decoded;
141
+ next();
142
+ } catch (error) {
143
+ res.status(401).json({ error: 'Invalid token' });
144
+ }
145
+ };
146
+
147
+ export const requireRole = (role) => (req, res, next) => {
148
+ if (req.user?.role !== role && req.user?.role !== 'admin') {
149
+ return res.status(403).json({ error: 'Insufficient permissions' });
150
+ }
151
+ next();
152
+ };
153
+ ```
154
+
155
+ #### 3.2 Actualizar rutas para protegerlas
156
+
157
+ En `watcher.routes.js`, agregar autenticación:
158
+
159
+ ```javascript
160
+ import { verifyAuth, requireRole } from '../middleware/auth.js';
161
+
162
+ export function initWatcherRoutes(app, watchService) {
163
+ // Endpoints de lectura (cualquier usuario autenticado)
164
+ router.get('/status', verifyAuth, (req, res) => {
165
+ // ... implementación ...
166
+ });
167
+
168
+ router.get('/queue-stats', verifyAuth, async (req, res) => {
169
+ // ... implementación ...
170
+ });
171
+
172
+ router.get('/directories', verifyAuth, (req, res) => {
173
+ // ... implementación ...
174
+ });
175
+
176
+ // Endpoints de control (solo admin)
177
+ router.post('/start', verifyAuth, requireRole('admin'), async (req, res) => {
178
+ // ... implementación ...
179
+ });
180
+
181
+ router.post('/stop', verifyAuth, requireRole('admin'), async (req, res) => {
182
+ // ... implementación ...
183
+ });
184
+
185
+ // ... resto de rutas ...
186
+ }
187
+ ```
188
+
189
+ ---
190
+
191
+ ### **Paso 4: Actualizar Frontend para Consumir Endpoints**
192
+
193
+ #### 4.1 Crear hook de React para monitorear watcher
194
+
195
+ Crear: `frontend/src/hooks/useWatcherMonitor.js`
196
+
197
+ ```javascript
198
+ import { useState, useEffect, useCallback } from 'react';
199
+
200
+ export const useWatcherMonitor = (pollInterval = 5000) => {
201
+ const [status, setStatus] = useState(null);
202
+ const [queue, setQueue] = useState(null);
203
+ const [directories, setDirectories] = useState([]);
204
+ const [loading, setLoading] = useState(false);
205
+ const [error, setError] = useState(null);
206
+
207
+ // Refrescar datos
208
+ const refresh = useCallback(async () => {
209
+ try {
210
+ setLoading(true);
211
+ setError(null);
212
+
213
+ const token = localStorage.getItem('token'); // O de donde lo tengas
214
+ const headers = {
215
+ 'Content-Type': 'application/json',
216
+ 'Authorization': `Bearer ${token}`,
217
+ };
218
+
219
+ const [statusRes, queueRes, dirRes] = await Promise.all([
220
+ fetch('/api/watcher/status', { headers }),
221
+ fetch('/api/watcher/queue-stats', { headers }),
222
+ fetch('/api/watcher/directories', { headers }),
223
+ ]);
224
+
225
+ if (!statusRes.ok || !queueRes.ok || !dirRes.ok) {
226
+ throw new Error('Failed to fetch watcher data');
227
+ }
228
+
229
+ setStatus(await statusRes.json());
230
+ setQueue(await queueRes.json());
231
+ setDirectories(await dirRes.json());
232
+ } catch (err) {
233
+ setError(err.message);
234
+ console.error('Error fetching watcher data:', err);
235
+ } finally {
236
+ setLoading(false);
237
+ }
238
+ }, []);
239
+
240
+ // Poll automático
241
+ useEffect(() => {
242
+ refresh(); // Fetch inicial
243
+ const interval = setInterval(refresh, pollInterval);
244
+ return () => clearInterval(interval);
245
+ }, [pollInterval, refresh]);
246
+
247
+ // Acciones
248
+ const startWatcher = useCallback(
249
+ async (directories) => {
250
+ const token = localStorage.getItem('token');
251
+ const res = await fetch('/api/watcher/start', {
252
+ method: 'POST',
253
+ headers: {
254
+ 'Content-Type': 'application/json',
255
+ 'Authorization': `Bearer ${token}`,
256
+ },
257
+ body: JSON.stringify({ directories, autoProcessing: true }),
258
+ });
259
+ if (!res.ok) throw new Error('Failed to start watcher');
260
+ await refresh();
261
+ return res.json();
262
+ },
263
+ [refresh]
264
+ );
265
+
266
+ const stopWatcher = useCallback(async () => {
267
+ const token = localStorage.getItem('token');
268
+ const res = await fetch('/api/watcher/stop', {
269
+ method: 'POST',
270
+ headers: { 'Authorization': `Bearer ${token}` },
271
+ });
272
+ if (!res.ok) throw new Error('Failed to stop watcher');
273
+ await refresh();
274
+ return res.json();
275
+ }, [refresh]);
276
+
277
+ return {
278
+ status,
279
+ queue,
280
+ directories,
281
+ loading,
282
+ error,
283
+ refresh,
284
+ startWatcher,
285
+ stopWatcher,
286
+ };
287
+ };
288
+ ```
289
+
290
+ #### 4.2 Usar el hook en un componente
291
+
292
+ ```javascript
293
+ // WatcherDashboard.jsx
294
+ import React from 'react';
295
+ import { useWatcherMonitor } from './hooks/useWatcherMonitor';
296
+
297
+ export const WatcherDashboard = () => {
298
+ const { status, queue, directories, loading, error, startWatcher, stopWatcher } =
299
+ useWatcherMonitor(5000); // Refrescar cada 5 segundos
300
+
301
+ if (loading && !status) return <div>Loading...</div>;
302
+ if (error) return <div className="error">Error: {error}</div>;
303
+
304
+ return (
305
+ <div className="watcher-dashboard">
306
+ <h1>🔍 File Watcher Monitor</h1>
307
+
308
+ {/* Status Section */}
309
+ <section className="status-card">
310
+ <h2>Estado</h2>
311
+ <div className="status-grid">
312
+ <div>
313
+ <span>Estado:</span>
314
+ <strong>{status?.isRunning ? '✅ Activo' : '❌ Detenido'}</strong>
315
+ </div>
316
+ <div>
317
+ <span>Directorios monitoreados:</span>
318
+ <strong>{status?.watchedDirectories}</strong>
319
+ </div>
320
+ <div>
321
+ <span>Auto-procesamiento:</span>
322
+ <strong>
323
+ {status?.autoProcessingEnabled ? '✅ Activo' : '❌ Inactivo'}
324
+ </strong>
325
+ </div>
326
+ </div>
327
+ </section>
328
+
329
+ {/* Queue Statistics Section */}
330
+ <section className="queue-stats-card">
331
+ <h2>Cola de Procesamiento</h2>
332
+ <div className="progress-bar">
333
+ <div
334
+ className="progress-fill"
335
+ style={{
336
+ width: `${queue?.progress?.percentComplete || 0}%`,
337
+ }}
338
+ />
339
+ </div>
340
+ <p>{queue?.progress?.percentComplete?.toFixed(1)}% completado</p>
341
+
342
+ <div className="queue-grid">
343
+ <div className="queue-item">
344
+ <span>Pendientes</span>
345
+ <strong>{queue?.queue?.pending || 0}</strong>
346
+ </div>
347
+ <div className="queue-item">
348
+ <span>Listos</span>
349
+ <strong>{queue?.queue?.readyToUpload || 0}</strong>
350
+ </div>
351
+ <div className="queue-item">
352
+ <span>Procesando</span>
353
+ <strong>{queue?.queue?.processing || 0}</strong>
354
+ </div>
355
+ <div className="queue-item">
356
+ <span>Subidos</span>
357
+ <strong>{queue?.queue?.uploaded || 0}</strong>
358
+ </div>
359
+ </div>
360
+ </section>
361
+
362
+ {/* Directories Section */}
363
+ <section className="directories-card">
364
+ <h2>Directorios Monitoreados</h2>
365
+ <ul>
366
+ {directories?.directories?.map((dir) => (
367
+ <li key={dir.path}>
368
+ <span>{dir.isReady ? '✅' : '⏳'}</span>
369
+ <span>{dir.path}</span>
370
+ <small>{dir.folderStructure}</small>
371
+ </li>
372
+ ))}
373
+ </ul>
374
+ </section>
375
+
376
+ {/* Control Buttons */}
377
+ <section className="controls">
378
+ <button
379
+ onClick={() => startWatcher(['/path/to/watch'])}
380
+ disabled={status?.isRunning}
381
+ >
382
+ Iniciar Watcher
383
+ </button>
384
+ <button onClick={stopWatcher} disabled={!status?.isRunning}>
385
+ Detener Watcher
386
+ </button>
387
+ </section>
388
+ </div>
389
+ );
390
+ };
391
+ ```
392
+
393
+ ---
394
+
395
+ ### **Paso 5: Documentar API con Swagger (Opcional)**
396
+
397
+ #### 5.1 Instalar dependencias
398
+
399
+ ```bash
400
+ cd arela-api
401
+ npm install swagger-ui-express swagger-jsdoc
402
+ ```
403
+
404
+ #### 5.2 Crear especificación de Swagger
405
+
406
+ Crear: `arela-api/src/swagger/watcher.swagger.js`
407
+
408
+ ```javascript
409
+ export const watcherSwaggerDef = {
410
+ paths: {
411
+ '/api/watcher/status': {
412
+ get: {
413
+ summary: 'Get watcher status',
414
+ tags: ['Watcher'],
415
+ responses: {
416
+ 200: {
417
+ description: 'Current watcher status',
418
+ schema: {
419
+ type: 'object',
420
+ properties: {
421
+ isRunning: { type: 'boolean' },
422
+ autoProcessingEnabled: { type: 'boolean' },
423
+ watchedDirectories: { type: 'number' },
424
+ stats: { type: 'object' },
425
+ },
426
+ },
427
+ },
428
+ 500: {
429
+ description: 'Error getting status',
430
+ },
431
+ },
432
+ },
433
+ },
434
+ '/api/watcher/start': {
435
+ post: {
436
+ summary: 'Start the watcher',
437
+ tags: ['Watcher'],
438
+ requestBody: {
439
+ required: true,
440
+ content: {
441
+ 'application/json': {
442
+ schema: {
443
+ type: 'object',
444
+ properties: {
445
+ directories: {
446
+ type: 'array',
447
+ items: { type: 'string' },
448
+ },
449
+ autoProcessing: { type: 'boolean' },
450
+ folderStructure: { type: 'string' },
451
+ },
452
+ required: ['directories'],
453
+ },
454
+ },
455
+ },
456
+ },
457
+ responses: {
458
+ 200: { description: 'Watcher started successfully' },
459
+ 400: { description: 'Invalid request' },
460
+ 500: { description: 'Error starting watcher' },
461
+ },
462
+ },
463
+ },
464
+ // ... agregar más endpoints ...
465
+ },
466
+ };
467
+ ```
468
+
469
+ #### 5.3 Integrar en app.js
470
+
471
+ ```javascript
472
+ import swaggerUi from 'swagger-ui-express';
473
+ import swaggerJsdoc from 'swagger-jsdoc';
474
+ import { watcherSwaggerDef } from './swagger/watcher.swagger.js';
475
+
476
+ const swaggerSpec = swaggerJsdoc({
477
+ definition: {
478
+ openapi: '3.0.0',
479
+ info: {
480
+ title: 'Arela API',
481
+ version: '1.0.0',
482
+ },
483
+ servers: [
484
+ { url: 'http://localhost:3000', description: 'Development' },
485
+ ],
486
+ ...watcherSwaggerDef,
487
+ },
488
+ apis: [],
489
+ });
490
+
491
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec));
492
+ ```
493
+
494
+ **Acceder en:** `http://localhost:3000/api-docs`
495
+
496
+ ---
497
+
498
+ ### **Paso 6: Testing**
499
+
500
+ #### 6.1 Crear tests de integración
501
+
502
+ Crear: `arela-api/test/watcher.test.js`
503
+
504
+ ```javascript
505
+ import request from 'supertest';
506
+ import app from '../src/app.js';
507
+
508
+ describe('Watcher API Routes', () => {
509
+ it('GET /api/watcher/status should return watcher status', async () => {
510
+ const response = await request(app)
511
+ .get('/api/watcher/status')
512
+ .set('Authorization', `Bearer ${validToken}`);
513
+
514
+ expect(response.status).toBe(200);
515
+ expect(response.body).toHaveProperty('isRunning');
516
+ expect(response.body).toHaveProperty('stats');
517
+ });
518
+
519
+ it('GET /api/watcher/queue-stats should return queue statistics', async () => {
520
+ const response = await request(app)
521
+ .get('/api/watcher/queue-stats')
522
+ .set('Authorization', `Bearer ${validToken}`);
523
+
524
+ expect(response.status).toBe(200);
525
+ expect(response.body).toHaveProperty('queue');
526
+ expect(response.body).toHaveProperty('progress');
527
+ });
528
+
529
+ it('POST /api/watcher/start should start watcher with directories', async () => {
530
+ const response = await request(app)
531
+ .post('/api/watcher/start')
532
+ .set('Authorization', `Bearer ${validToken}`)
533
+ .send({
534
+ directories: ['/test/dir'],
535
+ autoProcessing: true,
536
+ });
537
+
538
+ expect(response.status).toBe(200);
539
+ expect(response.body.success).toBe(true);
540
+ });
541
+ });
542
+ ```
543
+
544
+ #### 6.2 Ejecutar tests
545
+
546
+ ```bash
547
+ npm test -- test/watcher.test.js
548
+ ```
549
+
550
+ ---
551
+
552
+ ## 📋 Checklist Final
553
+
554
+ - [ ] Crear `src/services/index.js` en arela-uploader
555
+ - [ ] Actualizar `package.json` de arela-uploader con `exports`
556
+ - [ ] Instalar arela-uploader en arela-api
557
+ - [ ] Crear `src/routes/watcher.routes.js` en arela-api
558
+ - [ ] Integrar rutas en `app.js`
559
+ - [ ] Crear middleware de autenticación (opcional)
560
+ - [ ] Proteger rutas con autenticación
561
+ - [ ] Crear hook `useWatcherMonitor` en frontend
562
+ - [ ] Crear componente `WatcherDashboard` en frontend
563
+ - [ ] Agregar Swagger (opcional)
564
+ - [ ] Crear tests de integración
565
+ - [ ] Documentar endpoints
566
+ - [ ] Validar que funciona end-to-end
567
+
568
+ ---
569
+
570
+ ## 🧪 Testing End-to-End
571
+
572
+ ### 1. Iniciar arela-api
573
+ ```bash
574
+ cd arela-api
575
+ npm start
576
+ ```
577
+
578
+ ### 2. Probar endpoints con curl
579
+
580
+ ```bash
581
+ # Get status
582
+ curl http://localhost:3000/api/watcher/status \
583
+ -H "Authorization: Bearer YOUR_TOKEN"
584
+
585
+ # Get queue stats
586
+ curl http://localhost:3000/api/watcher/queue-stats \
587
+ -H "Authorization: Bearer YOUR_TOKEN"
588
+
589
+ # Start watcher
590
+ curl -X POST http://localhost:3000/api/watcher/start \
591
+ -H "Content-Type: application/json" \
592
+ -H "Authorization: Bearer YOUR_TOKEN" \
593
+ -d '{
594
+ "directories": ["/path/to/watch"],
595
+ "autoProcessing": true
596
+ }'
597
+
598
+ # Stop watcher
599
+ curl -X POST http://localhost:3000/api/watcher/stop \
600
+ -H "Authorization: Bearer YOUR_TOKEN"
601
+ ```
602
+
603
+ ### 3. Verificar en frontend
604
+ - Abrir DevTools (F12)
605
+ - Ir a Network tab
606
+ - Verificar que se hacen llamadas a `/api/watcher/*`
607
+ - Ver respuestas JSON en Preview
608
+
609
+ ---
610
+
611
+ ## 🎉 ¡Listo!
612
+
613
+ El frontend ahora puede monitorear el watcher en tiempo real a través de la API REST.
614
+