@arela/uploader 0.2.13 → 1.0.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 (43) hide show
  1. package/.env.template +66 -0
  2. package/README.md +263 -62
  3. package/docs/API_ENDPOINTS_FOR_DETECTION.md +647 -0
  4. package/docs/QUICK_REFERENCE_API_DETECTION.md +264 -0
  5. package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +200 -0
  6. package/package.json +3 -2
  7. package/scripts/cleanup-ds-store.js +109 -0
  8. package/scripts/cleanup-system-files.js +69 -0
  9. package/scripts/tests/phase-7-features.test.js +415 -0
  10. package/scripts/tests/signal-handling.test.js +275 -0
  11. package/scripts/tests/smart-watch-integration.test.js +554 -0
  12. package/scripts/tests/watch-service-integration.test.js +584 -0
  13. package/src/commands/UploadCommand.js +31 -4
  14. package/src/commands/WatchCommand.js +1342 -0
  15. package/src/config/config.js +270 -2
  16. package/src/document-type-shared.js +2 -0
  17. package/src/document-types/support-document.js +200 -0
  18. package/src/file-detection.js +9 -1
  19. package/src/index.js +163 -4
  20. package/src/services/AdvancedFilterService.js +505 -0
  21. package/src/services/AutoProcessingService.js +749 -0
  22. package/src/services/BenchmarkingService.js +381 -0
  23. package/src/services/DatabaseService.js +1019 -539
  24. package/src/services/ErrorMonitor.js +275 -0
  25. package/src/services/LoggingService.js +419 -1
  26. package/src/services/MonitoringService.js +401 -0
  27. package/src/services/PerformanceOptimizer.js +511 -0
  28. package/src/services/ReportingService.js +511 -0
  29. package/src/services/SignalHandler.js +255 -0
  30. package/src/services/SmartWatchDatabaseService.js +527 -0
  31. package/src/services/WatchService.js +783 -0
  32. package/src/services/upload/ApiUploadService.js +447 -3
  33. package/src/services/upload/MultiApiUploadService.js +233 -0
  34. package/src/services/upload/SupabaseUploadService.js +12 -5
  35. package/src/services/upload/UploadServiceFactory.js +24 -0
  36. package/src/utils/CleanupManager.js +262 -0
  37. package/src/utils/FileOperations.js +44 -0
  38. package/src/utils/WatchEventHandler.js +522 -0
  39. package/supabase/migrations/001_create_initial_schema.sql +366 -0
  40. package/supabase/migrations/002_align_with_arela_api_schema.sql +145 -0
  41. package/.envbackup +0 -37
  42. package/SUPABASE_UPLOAD_FIX.md +0 -157
  43. package/commands.md +0 -14
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Signal Handler Service
3
+ * Centralizes handling of system signals for graceful shutdown
4
+ * Manages SIGINT, SIGTERM, SIGHUP, SIGQUIT with cleanup coordination
5
+ */
6
+ export class SignalHandler {
7
+ /**
8
+ * Create a new SignalHandler instance
9
+ * @param {Object} logger - Logger service instance
10
+ * @param {Object} cleanupManager - Cleanup manager instance
11
+ */
12
+ constructor(logger, cleanupManager) {
13
+ this.logger = logger;
14
+ this.cleanupManager = cleanupManager;
15
+
16
+ /**
17
+ * Flag to prevent concurrent signal handling
18
+ * @type {boolean}
19
+ */
20
+ this.shutdownInProgress = false;
21
+
22
+ /**
23
+ * Signal received by process
24
+ * @type {string|null}
25
+ */
26
+ this.signalReceived = null;
27
+
28
+ /**
29
+ * Timestamp when signal was received
30
+ * @type {number|null}
31
+ */
32
+ this.signalTime = null;
33
+
34
+ /**
35
+ * Map of registered signal handlers
36
+ * @type {Map<string, Function>}
37
+ */
38
+ this.signalHandlers = new Map();
39
+
40
+ /**
41
+ * Signals to handle
42
+ * @type {string[]}
43
+ */
44
+ this.supportedSignals = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
45
+ }
46
+
47
+ /**
48
+ * Register signal handlers
49
+ * @param {Object} handlers - Map of signal handlers { signal: handler }
50
+ * @returns {void}
51
+ */
52
+ registerSignalHandlers(handlers = {}) {
53
+ for (const signal of this.supportedSignals) {
54
+ const handler = handlers[signal] || this.#createDefaultHandler(signal);
55
+
56
+ // Store handler reference
57
+ this.signalHandlers.set(signal, handler);
58
+
59
+ // Register with process
60
+ process.on(signal, () => this.#handleSignal(signal, handler));
61
+
62
+ this.logger.debug(`SignalHandler: Registered handler for ${signal}`);
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Handle incoming signal
68
+ * @private
69
+ * @param {string} signal - Signal name
70
+ * @param {Function} handler - Handler function
71
+ * @returns {Promise<void>}
72
+ */
73
+ async #handleSignal(signal, handler) {
74
+ // Prevent concurrent handling
75
+ if (this.shutdownInProgress) {
76
+ this.logger.warn(
77
+ `SignalHandler: Shutdown already in progress, ignoring ${signal}`,
78
+ );
79
+ return;
80
+ }
81
+
82
+ this.shutdownInProgress = true;
83
+ this.signalReceived = signal;
84
+ this.signalTime = Date.now();
85
+
86
+ this.logger.warn(
87
+ `\n\n🛑 SignalHandler: Received ${signal}, initiating graceful shutdown...`,
88
+ );
89
+
90
+ // Log signal details
91
+ this.#logSignalEvent(signal);
92
+
93
+ try {
94
+ // Perform cleanup
95
+ const cleanupResult = await this.cleanupManager.performCleanup(signal);
96
+
97
+ if (!cleanupResult.success) {
98
+ this.logger.error(
99
+ `SignalHandler: Cleanup had ${cleanupResult.failureCount} failures, but continuing with shutdown`,
100
+ );
101
+ }
102
+
103
+ // Execute signal-specific handler
104
+ if (handler && typeof handler === 'function') {
105
+ await handler();
106
+ }
107
+
108
+ // Determine exit code based on signal
109
+ const exitCode = this.#getExitCode(signal);
110
+ this.logger.info(
111
+ `SignalHandler: Shutdown complete, exiting with code ${exitCode}`,
112
+ );
113
+
114
+ process.exit(exitCode);
115
+ } catch (error) {
116
+ this.logger.error(
117
+ `SignalHandler: Error during signal handling: ${error.message}`,
118
+ );
119
+ process.exit(1);
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Create default handler for a signal
125
+ * @private
126
+ * @param {string} signal - Signal name
127
+ * @returns {Function} Default handler function
128
+ */
129
+ #createDefaultHandler(signal) {
130
+ return async () => {
131
+ this.logger.info(
132
+ `SignalHandler: Executing default handler for ${signal}`,
133
+ );
134
+ };
135
+ }
136
+
137
+ /**
138
+ * Get appropriate exit code for signal
139
+ * @private
140
+ * @param {string} signal - Signal name
141
+ * @returns {number} Exit code
142
+ */
143
+ #getExitCode(signal) {
144
+ const signalExitCodes = {
145
+ SIGINT: 130, // 128 + 2
146
+ SIGTERM: 143, // 128 + 15
147
+ SIGHUP: 129, // 128 + 1
148
+ SIGQUIT: 131, // 128 + 3
149
+ };
150
+
151
+ return signalExitCodes[signal] || 128;
152
+ }
153
+
154
+ /**
155
+ * Log signal event details
156
+ * @private
157
+ * @param {string} signal - Signal name
158
+ * @returns {void}
159
+ */
160
+ #logSignalEvent(signal) {
161
+ const signalDescriptions = {
162
+ SIGINT: 'Interrupt (Ctrl+C)',
163
+ SIGTERM: 'Termination (kill command)',
164
+ SIGHUP: 'Hangup (terminal closed)',
165
+ SIGQUIT: 'Quit (Ctrl+\\)',
166
+ };
167
+
168
+ const description = signalDescriptions[signal] || 'Unknown signal';
169
+
170
+ this.logger.info(`SignalHandler: Signal Details`);
171
+ this.logger.info(`├─ Signal: ${signal} (${description})`);
172
+ this.logger.info(`├─ Process ID: ${process.pid}`);
173
+ this.logger.info(`├─ Timestamp: ${new Date().toISOString()}`);
174
+ this.logger.info(
175
+ `├─ Memory Usage: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB`,
176
+ );
177
+ this.logger.info(`└─ Uptime: ${process.uptime().toFixed(2)}s`);
178
+ }
179
+
180
+ /**
181
+ * Check if shutdown is in progress
182
+ * @returns {boolean} True if shutdown is happening
183
+ */
184
+ isShuttingDown() {
185
+ return this.shutdownInProgress;
186
+ }
187
+
188
+ /**
189
+ * Get the signal that was received
190
+ * @returns {string|null} Signal name or null
191
+ */
192
+ getSignalReceived() {
193
+ return this.signalReceived;
194
+ }
195
+
196
+ /**
197
+ * Get timestamp when signal was received
198
+ * @returns {number|null} Timestamp in milliseconds or null
199
+ */
200
+ getSignalTime() {
201
+ return this.signalTime;
202
+ }
203
+
204
+ /**
205
+ * Generate signal event report
206
+ * @returns {string} Formatted report
207
+ */
208
+ generateSignalReport() {
209
+ if (!this.signalReceived) {
210
+ return 'No signal received yet';
211
+ }
212
+
213
+ const duration = this.signalTime ? Date.now() - this.signalTime : 0;
214
+
215
+ let report =
216
+ '\n═══════════════════════════════════════════════════════════\n';
217
+ report += 'SIGNAL HANDLING REPORT\n';
218
+ report += '═══════════════════════════════════════════════════════════\n\n';
219
+ report += `Signal: ${this.signalReceived}\n`;
220
+ report += `Process ID: ${process.pid}\n`;
221
+ report += `Received At: ${new Date(this.signalTime).toISOString()}\n`;
222
+ report += `Shutdown Duration: ${duration}ms\n`;
223
+ report += `Shutdown Status: ${this.shutdownInProgress ? 'IN PROGRESS' : 'COMPLETE'}\n`;
224
+ report += '═══════════════════════════════════════════════════════════\n';
225
+
226
+ return report;
227
+ }
228
+
229
+ /**
230
+ * Reset signal handler state (useful for testing)
231
+ * @returns {void}
232
+ */
233
+ reset() {
234
+ this.shutdownInProgress = false;
235
+ this.signalReceived = null;
236
+ this.signalTime = null;
237
+ this.logger.debug('SignalHandler: Reset to initial state');
238
+ }
239
+ }
240
+
241
+ // Export as singleton
242
+ let instance = null;
243
+
244
+ export function createSignalHandler(logger, cleanupManager) {
245
+ if (!instance) {
246
+ instance = new SignalHandler(logger, cleanupManager);
247
+ }
248
+ return instance;
249
+ }
250
+
251
+ export function getSignalHandler() {
252
+ return instance;
253
+ }
254
+
255
+ export default SignalHandler;