@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.
Files changed (79) 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 +8 -0
  29. package/src/config/config.js +2 -2
  30. package/src/file-detection.js +42 -1
  31. package/src/scoring/scoring-engine.js +35 -7
  32. package/.vscode/settings.json +0 -1
  33. package/coverage/IdentifyCommand.js.html +0 -1462
  34. package/coverage/PropagateCommand.js.html +0 -1507
  35. package/coverage/PushCommand.js.html +0 -1504
  36. package/coverage/ScanCommand.js.html +0 -1654
  37. package/coverage/UploadCommand.js.html +0 -1846
  38. package/coverage/WatchCommand.js.html +0 -4111
  39. package/coverage/base.css +0 -224
  40. package/coverage/block-navigation.js +0 -87
  41. package/coverage/favicon.png +0 -0
  42. package/coverage/index.html +0 -191
  43. package/coverage/lcov-report/IdentifyCommand.js.html +0 -1462
  44. package/coverage/lcov-report/PropagateCommand.js.html +0 -1507
  45. package/coverage/lcov-report/PushCommand.js.html +0 -1504
  46. package/coverage/lcov-report/ScanCommand.js.html +0 -1654
  47. package/coverage/lcov-report/UploadCommand.js.html +0 -1846
  48. package/coverage/lcov-report/WatchCommand.js.html +0 -4111
  49. package/coverage/lcov-report/base.css +0 -224
  50. package/coverage/lcov-report/block-navigation.js +0 -87
  51. package/coverage/lcov-report/favicon.png +0 -0
  52. package/coverage/lcov-report/index.html +0 -191
  53. package/coverage/lcov-report/prettify.css +0 -1
  54. package/coverage/lcov-report/prettify.js +0 -2
  55. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  56. package/coverage/lcov-report/sorter.js +0 -210
  57. package/coverage/lcov.info +0 -1937
  58. package/coverage/prettify.css +0 -1
  59. package/coverage/prettify.js +0 -2
  60. package/coverage/sort-arrow-sprite.png +0 -0
  61. package/coverage/sorter.js +0 -210
  62. package/docs/API_ENDPOINTS_FOR_DETECTION.md +0 -647
  63. package/docs/API_RETRY_MECHANISM.md +0 -338
  64. package/docs/ARELA_IDENTIFY_IMPLEMENTATION.md +0 -489
  65. package/docs/ARELA_IDENTIFY_QUICKREF.md +0 -186
  66. package/docs/ARELA_PROPAGATE_IMPLEMENTATION.md +0 -581
  67. package/docs/ARELA_PROPAGATE_QUICKREF.md +0 -272
  68. package/docs/ARELA_PUSH_IMPLEMENTATION.md +0 -577
  69. package/docs/ARELA_PUSH_QUICKREF.md +0 -322
  70. package/docs/ARELA_SCAN_IMPLEMENTATION.md +0 -373
  71. package/docs/ARELA_SCAN_QUICKREF.md +0 -139
  72. package/docs/CROSS_PLATFORM_PATH_HANDLING.md +0 -597
  73. package/docs/DETECTION_ATTEMPT_TRACKING.md +0 -414
  74. package/docs/MIGRATION_UPLOADER_TO_FILE_STATS.md +0 -1020
  75. package/docs/MULTI_LEVEL_DIRECTORY_SCANNING.md +0 -494
  76. package/docs/QUICK_REFERENCE_API_DETECTION.md +0 -264
  77. package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +0 -200
  78. package/docs/STATS_COMMAND_SEQUENCE_DIAGRAM.md +0 -287
  79. 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)