@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,395 @@
1
+ # Arquitectura de Watch Mode con Auto-Processing Pipeline
2
+
3
+ ## πŸ—οΈ Diagrama de Componentes
4
+
5
+ ```
6
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
7
+ β”‚ arela watch β”‚
8
+ β”‚ (index.js - CLI) β”‚
9
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
10
+ β”‚
11
+ β–Ό
12
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
13
+ β”‚ WatchCommand.js β”‚
14
+ β”‚ β€’ Parsea directorios con JSON (WATCH_DIRECTORY_CONFIGS) β”‚
15
+ β”‚ β€’ Crea configuraciones de directorio con folderStructure β”‚
16
+ β”‚ β€’ Inicializa WatchService con directoryConfigs β”‚
17
+ β”‚ β€’ Habilita auto-processing β”‚
18
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
19
+ β”‚
20
+ β–Ό
21
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
22
+ β”‚ WatchService.js β”‚
23
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
24
+ β”‚ β”‚ Watchers (chokidar) β”‚ β”‚
25
+ β”‚ β”‚ β€’ Monitorea cambios en filesystem β”‚ β”‚
26
+ β”‚ β”‚ β€’ Emite eventos: add, change, unlink β”‚ β”‚
27
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
28
+ β”‚ β”‚ β”‚
29
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
30
+ β”‚ β”‚ #handleFileAdded() β”‚ (evento: add) β”‚ β”‚
31
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
32
+ β”‚ β”‚ β”‚
33
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
34
+ β”‚ β”‚ #triggerAutoPipeline()β”‚ (if autoProcessing) β”‚ β”‚
35
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
36
+ β”‚ β”‚ β”‚
37
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
38
+ β”‚ β”‚ directoryConfigs Map β”‚ findWatchDirectory() β”‚ β”‚
39
+ β”‚ β”‚ β€’ watchDir -> config β”‚ folderStructure β”‚ β”‚
40
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
41
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
42
+ β”‚
43
+ β–Ό
44
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
45
+ β”‚ AutoProcessingService.js β”‚
46
+ β”‚ (4-Step Pipeline) β”‚
47
+ β”‚ β”‚
48
+ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
49
+ β”‚ β”‚ STEP 1 β”‚ β”‚ STEP 2 β”‚ β”‚ STEP 3 β”‚ β”‚ STEP 4 β”‚ β”‚
50
+ β”‚ β”‚ Stats β”‚β†’ β”‚ Detect β”‚β†’ β”‚ Propagate β”‚β†’ β”‚ Upload β”‚ β”‚
51
+ β”‚ β”‚ Only β”‚ β”‚ PDFs β”‚ β”‚ Arela Path β”‚ β”‚ by RFC β”‚ β”‚
52
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
53
+ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
54
+ β”‚ β–Ό β–Ό β–Ό β–Ό β”‚
55
+ β”‚ UploadCommand DatabaseService DatabaseService UploadCommand β”‚
56
+ β”‚ β”‚
57
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
58
+ ```
59
+
60
+ ## πŸ“Š Flujo de Datos
61
+
62
+ ### Secuencia de Eventos
63
+
64
+ ```
65
+ 1. Usuario coloca archivo en directorio monitoreado
66
+ ↓
67
+ 2. Chokidar detecta evento 'add'
68
+ ↓
69
+ 3. WatchService.#handleFileAdded() es invocado
70
+ ↓
71
+ 4. Si autoProcessingEnabled:
72
+ - WatchService.#triggerAutoPipeline(filePath) es llamado
73
+ ↓
74
+ 5. Se identifica el watchDir correspondiente
75
+ - Se obtiene folderStructure de directoryConfigs
76
+ ↓
77
+ 6. AutoProcessingService.executeProcessingPipeline() inicia
78
+ ↓
79
+ 7. Secuencia de 4 pasos:
80
+ - Step 1: stats --stats-only
81
+ - Step 2: detect --detect-pdfs
82
+ - Step 3: detect --propagate-arela-path
83
+ - Step 4: upload --upload-by-rfc --folder-structure
84
+ ↓
85
+ 8. Resultado es loguead y resumido
86
+ ```
87
+
88
+ ## πŸ”Œ IntegraciΓ³n de Componentes
89
+
90
+ ### config.js
91
+ ```javascript
92
+ // Parsea WATCH_DIRECTORY_CONFIGS desde .env
93
+ watch.directoryConfigs = JSON.parse(process.env.WATCH_DIRECTORY_CONFIGS)
94
+ // Resultado:
95
+ // {
96
+ // "../../Documents/2022": "estructura-2022",
97
+ // "../../Documents/2023": "estructura-2023"
98
+ // }
99
+ ```
100
+
101
+ ### WatchCommand.js
102
+ ```javascript
103
+ // Convierte configuraciΓ³n a array de objetos
104
+ const directories = [
105
+ { path: "../../Documents/2022", folderStructure: "estructura-2022" },
106
+ { path: "../../Documents/2023", folderStructure: "estructura-2023" }
107
+ ]
108
+
109
+ // Pasa directoryConfigs a WatchService
110
+ for (const dirConfig of directories) {
111
+ await watchService.addWatcher(dirPath, options, dirConfig)
112
+ }
113
+
114
+ // Habilita auto-processing
115
+ watchService.enableAutoProcessing({ batchSize: 10 })
116
+ ```
117
+
118
+ ### WatchService.js
119
+ ```javascript
120
+ // Almacena configuraciΓ³n de directorios
121
+ directoryConfigs = new Map([
122
+ ["path/to/Documents/2022", { path: "...", folderStructure: "estructura-2022" }],
123
+ ["path/to/Documents/2023", { path: "...", folderStructure: "estructura-2023" }]
124
+ ])
125
+
126
+ // Cuando detecta archivo nuevo
127
+ #handleFileAdded(filePath) {
128
+ if (this.autoProcessingEnabled) {
129
+ this.#triggerAutoPipeline(filePath)
130
+ }
131
+ }
132
+
133
+ // Encuentra configuraciΓ³n del directorio
134
+ #triggerAutoPipeline(filePath) {
135
+ const watchDir = this.#findWatchDirectory(filePath)
136
+ const dirConfig = this.directoryConfigs.get(watchDir)
137
+ const folderStructure = dirConfig.folderStructure
138
+
139
+ // Ejecuta pipeline con folderStructure
140
+ autoProcessingService.executeProcessingPipeline({
141
+ filePath,
142
+ watchDir,
143
+ folderStructure,
144
+ batchSize: 10
145
+ })
146
+ }
147
+ ```
148
+
149
+ ### AutoProcessingService.js
150
+ ```javascript
151
+ // Ejecuta 4 pasos secuencialmente
152
+ async executeProcessingPipeline(options) {
153
+ // Step 1: stats
154
+ await this.#executeStatsOnly(options)
155
+
156
+ // Step 2: detect
157
+ await this.#executeDetectPdfs(options)
158
+
159
+ // Step 3: propagate
160
+ await this.#executePropagateArelaPath()
161
+
162
+ // Step 4: upload with folderStructure
163
+ await this.#executeUploadByRfc({
164
+ ...options,
165
+ folderStructure: options.folderStructure // ← Se usa aquΓ­
166
+ })
167
+ }
168
+ ```
169
+
170
+ ## πŸ“ Estructura de Archivos Modificados
171
+
172
+ ```
173
+ src/
174
+ β”œβ”€β”€ index.js (Sin cambios mayores)
175
+ β”œβ”€β”€ config/
176
+ β”‚ └── config.js (βœ… Actualizado: #loadWatchConfig)
177
+ β”œβ”€β”€ commands/
178
+ β”‚ β”œβ”€β”€ WatchCommand.js (βœ… Actualizado: #parseDirectories, auto-processing)
179
+ β”‚ └── UploadCommand.js (Sin cambios)
180
+ β”œβ”€β”€ services/
181
+ β”‚ β”œβ”€β”€ WatchService.js (βœ… Actualizado: directoryConfigs, auto-pipeline)
182
+ β”‚ β”œβ”€β”€ AutoProcessingService.js (πŸ†• Creado: 4-step pipeline)
183
+ β”‚ β”œβ”€β”€ DatabaseService.js (Sin cambios)
184
+ β”‚ └── LoggingService.js (Sin cambios)
185
+ └── utils/
186
+ └── WatchEventHandler.js (βœ… Actualizado: processNewFilesWithPipeline)
187
+
188
+ .env (βœ… Actualizado: WATCH_DIRECTORY_CONFIGS)
189
+ .env.template (βœ… Actualizado: nueva configuraciΓ³n)
190
+ docs/
191
+ └── WATCH_AUTO_PIPELINE.md (πŸ†• Creado: esta documentaciΓ³n)
192
+ ```
193
+
194
+ ## πŸ”„ Estados y Transiciones
195
+
196
+ ### WatchService Estados
197
+
198
+ ```
199
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
200
+ β”‚ IDLE β”‚
201
+ β”‚(created) β”‚
202
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
203
+ β”‚ addWatcher()
204
+ β–Ό
205
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
206
+ β”‚ WATCHING β”‚ ← directoryConfigs se cargan aquΓ­
207
+ β”‚ β”‚
208
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
209
+ β”‚ autoProcessing = true
210
+ β–Ό
211
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
212
+ β”‚ AUTO-PROCESSING β”‚
213
+ β”‚ ENABLED β”‚
214
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
215
+ β”‚ detecta archivo new
216
+ β–Ό
217
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
218
+ β”‚ EXECUTING PIPELINE β”‚
219
+ β”‚ (AutoProcessing β”‚
220
+ β”‚ Service) β”‚
221
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
222
+ β”‚ pipeline completa
223
+ β–Ό
224
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
225
+ β”‚ WATCHING β”‚ ← Vuelve a estado de espera
226
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
227
+ ```
228
+
229
+ ### Pipeline Estados
230
+
231
+ ```
232
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
233
+ β”‚ PENDING β”‚
234
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
235
+ β”‚ executeProcessingPipeline()
236
+ β–Ό
237
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
238
+ β”‚ STEP 1 β”‚
239
+ β”‚ STATS ONLY β”‚
240
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
241
+ β”‚ success
242
+ β–Ό
243
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
244
+ β”‚ STEP 2 β”‚
245
+ β”‚ DETECT PDFS β”‚
246
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
247
+ β”‚ success
248
+ β–Ό
249
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
250
+ β”‚ STEP 3 β”‚
251
+ β”‚ PROPAGATE β”‚
252
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
253
+ β”‚ success/warning
254
+ β–Ό
255
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
256
+ β”‚ STEP 4 β”‚
257
+ β”‚ UPLOAD RFC β”‚
258
+ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
259
+ β”‚ success/fail
260
+ β–Ό
261
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
262
+ β”‚ COMPLETED β”‚
263
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
264
+ ```
265
+
266
+ ## 🎯 Caso de Uso Detallado
267
+
268
+ ### Escenario: Nuevo archivo en Documents/2022
269
+
270
+ #### ConfiguraciΓ³n
271
+ ```env
272
+ WATCH_DIRECTORY_CONFIGS={"../../Documents/2022":"estructura-2022"}
273
+ WATCH_ENABLED=true
274
+ ```
275
+
276
+ #### EjecuciΓ³n
277
+
278
+ 1. **Evento del Filesystem**
279
+ - Usuario: `cp documento.pdf ../../Documents/2022/`
280
+ - Chokidar: Detecta evento 'add' para el archivo
281
+
282
+ 2. **WatchService**
283
+ ```
284
+ #handleFileAdded(filePath) β†’
285
+ #triggerAutoPipeline(filePath) β†’
286
+ #findWatchDirectory() β†’ "../../Documents/2022" β†’
287
+ directoryConfigs.get() β†’ { folderStructure: "estructura-2022" } β†’
288
+ autoProcessingService.executeProcessingPipeline()
289
+ ```
290
+
291
+ 3. **AutoProcessingService - Step 1**
292
+ ```
293
+ #executeStatsOnly() β†’
294
+ UploadCommand.execute({ statsOnly: true }) β†’
295
+ Database: INSERT INTO uploads VALUES (...)
296
+ ```
297
+
298
+ 4. **AutoProcessingService - Step 2**
299
+ ```
300
+ #executeDetectPdfs() β†’
301
+ DatabaseService.detectPedimentosInDatabase() β†’
302
+ Database: UPDATE uploads SET document_type = 'pedimento-simplificado' WHERE ...
303
+ ```
304
+
305
+ 5. **AutoProcessingService - Step 3**
306
+ ```
307
+ #executePropagateArelaPath() β†’
308
+ DatabaseService.propagateArelaPath() β†’
309
+ Database: UPDATE uploads SET arela_path = ... WHERE original_path = ...
310
+ ```
311
+
312
+ 6. **AutoProcessingService - Step 4**
313
+ ```
314
+ #executeUploadByRfc() β†’
315
+ DatabaseService.uploadFilesByRfc({ folderStructure: "estructura-2022" }) β†’
316
+ UploadService: POST /api/upload/file (with folderStructure header/param) β†’
317
+ Result: File uploaded to Arela with path bucket/estructura-2022/...
318
+ ```
319
+
320
+ 7. **Resultado Final**
321
+ ```
322
+ βœ… Pipeline execution complete
323
+ - Stats collected
324
+ - PDFs detected
325
+ - Arela paths propagated
326
+ - Files uploaded with structure
327
+ - All 4 steps successful
328
+ ```
329
+
330
+ ## πŸ§ͺ Testing
331
+
332
+ ### Unit Tests Recomendados
333
+
334
+ ```javascript
335
+ // Test: directoryConfigs se cargan correctamente
336
+ describe('WatchService', () => {
337
+ it('should load directory configs from addWatcher', () => {
338
+ const dirConfig = { path: 'test', folderStructure: 'test-struct' }
339
+ watchService.addWatcher('test', {}, dirConfig)
340
+ expect(watchService.directoryConfigs.get(path.resolve('test'))).toEqual(...)
341
+ })
342
+ })
343
+
344
+ // Test: auto-processing se habilita
345
+ it('should enable auto-processing', () => {
346
+ watchService.enableAutoProcessing({ batchSize: 10 })
347
+ expect(watchService.isAutoProcessingEnabled()).toBe(true)
348
+ })
349
+
350
+ // Test: pipeline se ejecuta en archivo nuevo
351
+ it('should trigger pipeline on file added', async () => {
352
+ // Mock AutoProcessingService
353
+ // Simulate #handleFileAdded
354
+ // Verify pipeline was called
355
+ })
356
+ ```
357
+
358
+ ## πŸ“ˆ MΓ©tricas y Monitoreo
359
+
360
+ ### Stats Disponibles
361
+
362
+ ```javascript
363
+ // WatchService stats
364
+ {
365
+ filesAdded: 42,
366
+ filesModified: 15,
367
+ filesRemoved: 3,
368
+ uploadsTriggered: 10,
369
+ pipelinesTriggered: 8, // ← Novo
370
+ errorsEncountered: 0,
371
+ watchedDirectories: 2,
372
+ activeWatchers: 2,
373
+ isRunning: true,
374
+ autoProcessingEnabled: true // ← Novo
375
+ }
376
+ ```
377
+
378
+ ## πŸ” Consideraciones de Seguridad
379
+
380
+ 1. **ValidaciΓ³n de Ruta**
381
+ - Se valida que el archivo estΓ‘ en directorio vigilado
382
+ - Se previene procesamiento de archivos fuera del scope
383
+
384
+ 2. **PrevenciΓ³n de Concurrencia**
385
+ - Solo un pipeline por vez (`this.isProcessing`)
386
+ - Se colan nuevas solicitudes mientras uno estΓ‘ en ejecuciΓ³n
387
+
388
+ 3. **Manejo de Errores**
389
+ - Errores en pasos iniciales detienen el pipeline
390
+ - Errores posteriores se loguean pero continΓΊan
391
+ - No se pierden datos incluso con fallos
392
+
393
+ ---
394
+
395
+ Para implementaciΓ³n y uso, ver [WATCH_AUTO_PIPELINE.md](WATCH_AUTO_PIPELINE.md)