@tamyla/clodo-framework 3.1.4 → 3.1.8

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 (62) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/bin/clodo-service.js +29 -989
  3. package/bin/database/enterprise-db-manager.js +7 -5
  4. package/bin/security/security-cli.js +0 -0
  5. package/bin/service-management/create-service.js +0 -0
  6. package/bin/service-management/init-service.js +0 -0
  7. package/bin/shared/cloudflare/domain-discovery.js +11 -10
  8. package/bin/shared/cloudflare/ops.js +1 -1
  9. package/bin/shared/config/ConfigurationManager.js +539 -0
  10. package/bin/shared/config/index.js +13 -1
  11. package/bin/shared/database/connection-manager.js +2 -2
  12. package/bin/shared/database/orchestrator.js +5 -4
  13. package/bin/shared/deployment/auditor.js +9 -8
  14. package/bin/shared/logging/Logger.js +214 -0
  15. package/bin/shared/monitoring/production-monitor.js +21 -9
  16. package/bin/shared/utils/ErrorHandler.js +675 -0
  17. package/bin/shared/utils/error-recovery.js +33 -13
  18. package/bin/shared/utils/file-manager.js +162 -0
  19. package/bin/shared/utils/formatters.js +247 -0
  20. package/bin/shared/utils/index.js +14 -4
  21. package/bin/shared/validation/ValidationRegistry.js +143 -0
  22. package/dist/deployment/auditor.js +23 -8
  23. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  24. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +401 -0
  25. package/dist/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  26. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  27. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  28. package/dist/deployment/orchestration/index.js +17 -0
  29. package/dist/index.js +12 -0
  30. package/dist/orchestration/modules/DomainResolver.js +8 -6
  31. package/dist/orchestration/multi-domain-orchestrator.js +13 -1
  32. package/dist/security/index.js +2 -2
  33. package/dist/service-management/ConfirmationEngine.js +8 -7
  34. package/dist/service-management/ErrorTracker.js +7 -2
  35. package/dist/service-management/InputCollector.js +31 -16
  36. package/dist/service-management/ServiceCreator.js +22 -7
  37. package/dist/service-management/ServiceInitializer.js +12 -18
  38. package/dist/shared/cloudflare/domain-discovery.js +11 -10
  39. package/dist/shared/cloudflare/ops.js +1 -1
  40. package/dist/shared/config/ConfigurationManager.js +519 -0
  41. package/dist/shared/config/index.js +5 -1
  42. package/dist/shared/database/connection-manager.js +2 -2
  43. package/dist/shared/database/orchestrator.js +13 -4
  44. package/dist/shared/deployment/auditor.js +23 -8
  45. package/dist/shared/logging/Logger.js +209 -0
  46. package/dist/shared/monitoring/production-monitor.js +24 -8
  47. package/dist/{utils → shared/utils}/ErrorHandler.js +306 -28
  48. package/dist/shared/utils/error-recovery.js +33 -13
  49. package/dist/shared/utils/file-manager.js +155 -0
  50. package/dist/shared/utils/formatters.js +215 -0
  51. package/dist/shared/utils/index.js +14 -4
  52. package/dist/shared/validation/ValidationRegistry.js +126 -0
  53. package/dist/utils/config/unified-config-manager.js +14 -12
  54. package/dist/utils/deployment/config-cache.js +3 -1
  55. package/dist/utils/deployment/secret-generator.js +32 -29
  56. package/dist/utils/framework-config.js +6 -3
  57. package/dist/utils/ui-structures-loader.js +3 -0
  58. package/dist/worker/integration.js +11 -1
  59. package/package.json +31 -3
  60. package/dist/config/FeatureManager.js +0 -426
  61. package/dist/config/features.js +0 -230
  62. package/dist/utils/error-recovery.js +0 -240
@@ -13,6 +13,7 @@ import { existsSync } from 'fs';
13
13
  import { join, dirname } from 'path';
14
14
  import { fileURLToPath } from 'url';
15
15
  import { promisify } from 'util';
16
+ import { logger } from '../logging/Logger.js';
16
17
 
17
18
  const execAsync = promisify(exec);
18
19
 
@@ -186,7 +187,7 @@ export class DatabaseOrchestrator {
186
187
  console.log(`✅ ${env} environment completed successfully`);
187
188
 
188
189
  } catch (error) {
189
- console.error(`❌ ${env} environment failed: ${error.message}`);
190
+ logger.error(`${env} environment failed`, { error: error.message });
190
191
 
191
192
  results.environments[env] = {
192
193
  status: 'failed',
@@ -261,7 +262,7 @@ export class DatabaseOrchestrator {
261
262
  results.migrationsApplied += dbResult.migrationsApplied || 0;
262
263
 
263
264
  } catch (error) {
264
- console.error(`Database ${dbConfig.name} migration failed: ${error.message}`);
265
+ logger.error(`Database ${dbConfig.name} migration failed`, { error: error.message });
265
266
  results.databases[dbConfig.name] = {
266
267
  status: 'failed',
267
268
  error: error.message
@@ -522,7 +523,7 @@ export class DatabaseOrchestrator {
522
523
  );
523
524
  cleanupResults.operations[dbConfig.name] = cleanupResult;
524
525
  } catch (error) {
525
- console.error(`❌ Cleanup failed for ${dbConfig.name}: ${error.message}`);
526
+ logger.error(`Cleanup failed for ${dbConfig.name}`, { error: error.message });
526
527
  cleanupResults.operations[dbConfig.name] = {
527
528
  status: 'failed',
528
529
  error: error.message
@@ -718,7 +719,7 @@ export class DatabaseOrchestrator {
718
719
  writeFile(this.backupPaths.audit, logLine);
719
720
  }
720
721
  } catch (error) {
721
- console.warn(`⚠️ Failed to log audit event: ${error.message}`);
722
+ logger.warn('Failed to log audit event', { error: error.message });
722
723
  }
723
724
  }
724
725
  }
@@ -19,6 +19,7 @@
19
19
  import { existsSync, writeFileSync, appendFileSync, mkdirSync, readFileSync, readdirSync, statSync } from 'fs';
20
20
  import { join, dirname } from 'path';
21
21
  import { execSync } from 'child_process';
22
+ import { logger } from '../logging/Logger.js';
22
23
 
23
24
  export class DeploymentAuditor {
24
25
  constructor(options = {}) {
@@ -253,7 +254,7 @@ export class DeploymentAuditor {
253
254
  const deployment = this.currentSession.deployments.get(deploymentId);
254
255
 
255
256
  if (!deployment) {
256
- console.warn(`⚠️ Deployment not found for phase logging: ${deploymentId}`);
257
+ logger.warn('Deployment not found for phase logging', { deploymentId });
257
258
  return;
258
259
  }
259
260
 
@@ -319,7 +320,7 @@ export class DeploymentAuditor {
319
320
  context
320
321
  });
321
322
 
322
- console.error(`❌ Deployment error logged: ${deploymentId}`);
323
+ logger.error('Deployment error logged', { deploymentId });
323
324
  }
324
325
 
325
326
  /**
@@ -519,7 +520,7 @@ export class DeploymentAuditor {
519
520
  }
520
521
 
521
522
  } catch (error) {
522
- console.error(`⚠️ Failed to write audit log: ${error.message}`);
523
+ logger.error('Failed to write audit log', { error: error.message });
523
524
  }
524
525
  }
525
526
 
@@ -542,7 +543,7 @@ export class DeploymentAuditor {
542
543
  });
543
544
 
544
545
  } catch (error) {
545
- console.error(`⚠️ Failed to rotate log file: ${error.message}`);
546
+ logger.error('Failed to rotate log file', { error: error.message });
546
547
  }
547
548
  }
548
549
 
@@ -555,7 +556,7 @@ export class DeploymentAuditor {
555
556
  const deployment = this.currentSession.deployments.get(deploymentId);
556
557
 
557
558
  if (!deployment) {
558
- console.warn(`⚠️ Cannot generate report: deployment ${deploymentId} not found`);
559
+ logger.warn('Cannot generate report: deployment not found', { deploymentId });
559
560
  return null;
560
561
  }
561
562
 
@@ -808,7 +809,7 @@ export class DeploymentAuditor {
808
809
  */
809
810
  async sendSecurityAlert(securityEvent) {
810
811
  if (!this.config.alertWebhook) {
811
- console.warn('⚠️ Security alert webhook not configured');
812
+ logger.warn('Security alert webhook not configured');
812
813
  return;
813
814
  }
814
815
 
@@ -830,7 +831,7 @@ export class DeploymentAuditor {
830
831
  });
831
832
 
832
833
  } catch (error) {
833
- console.error(`❌ Failed to send security alert: ${error.message}`);
834
+ logger.error('Failed to send security alert', { error: error.message });
834
835
  }
835
836
  }
836
837
 
@@ -896,7 +897,7 @@ export class DeploymentAuditor {
896
897
  console.log(`🧹 Audit cleanup completed: ${cleanupResults.filesRemoved} files removed`);
897
898
 
898
899
  } catch (error) {
899
- console.error(`❌ Audit cleanup failed: ${error.message}`);
900
+ logger.error('Audit cleanup failed', { error: error.message });
900
901
  cleanupResults.errors.push({ general: error.message });
901
902
  }
902
903
 
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Unified Logger for Clodo Framework
3
+ * Replaces: 6 separate logging implementations
4
+ * Savings: 300+ lines, unified logging across entire codebase
5
+ *
6
+ * @version 1.0.0
7
+ */
8
+
9
+ import { appendFileSync, mkdirSync, existsSync } from 'fs';
10
+ import { dirname } from 'path';
11
+
12
+ const LOG_LEVELS = {
13
+ DEBUG: 0,
14
+ INFO: 1,
15
+ WARN: 2,
16
+ ERROR: 3,
17
+ FATAL: 4
18
+ };
19
+
20
+ export class Logger {
21
+ constructor(context = {}) {
22
+ this.context = context;
23
+ this.logLevel = this._parseLogLevel(process.env.LOG_LEVEL || 'info');
24
+ this.logDir = process.env.LOG_DIR || null;
25
+ this.logFile = null;
26
+ this.cache = new Map();
27
+ this.isDev = process.env.NODE_ENV !== 'production';
28
+
29
+ if (this.logDir) {
30
+ mkdirSync(this.logDir, { recursive: true });
31
+ }
32
+ }
33
+
34
+ /**
35
+ * DEBUG level logging
36
+ */
37
+ debug(message, data = {}) {
38
+ if (this.logLevel > LOG_LEVELS.DEBUG) return;
39
+ this._log('DEBUG', message, data);
40
+ }
41
+
42
+ /**
43
+ * INFO level logging
44
+ */
45
+ info(message, data = {}) {
46
+ if (this.logLevel > LOG_LEVELS.INFO) return;
47
+ this._log('INFO', message, data);
48
+ }
49
+
50
+ /**
51
+ * WARN level logging
52
+ */
53
+ warn(message, data = {}) {
54
+ if (this.logLevel > LOG_LEVELS.WARN) return;
55
+ this._log('WARN', message, data);
56
+ }
57
+
58
+ /**
59
+ * ERROR level logging
60
+ */
61
+ error(message, data = {}) {
62
+ if (this.logLevel > LOG_LEVELS.ERROR) return;
63
+ this._log('ERROR', message, data);
64
+ }
65
+
66
+ /**
67
+ * FATAL level logging (exits process)
68
+ */
69
+ fatal(message, data = {}) {
70
+ this._log('FATAL', message, data);
71
+ if (!this.isDev) {
72
+ process.exit(1);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Log HTTP request
78
+ */
79
+ logRequest(request, context = {}) {
80
+ this.info('HTTP Request', {
81
+ method: request.method,
82
+ url: request.url,
83
+ userAgent: request.headers?.get?.('User-Agent'),
84
+ ...context
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Log deployment event
90
+ */
91
+ logDeployment(deploymentId, message, context = {}) {
92
+ this.info(`[Deployment ${deploymentId}] ${message}`, {
93
+ deploymentId,
94
+ ...context
95
+ });
96
+ }
97
+
98
+ /**
99
+ * Log audit event
100
+ */
101
+ logAudit(eventType, domain, details = {}) {
102
+ this.info(`[Audit] ${eventType} for ${domain}`, {
103
+ eventType,
104
+ domain,
105
+ ...details
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Log performance metric
111
+ */
112
+ logPerformance(operation, durationMs, context = {}) {
113
+ const level = durationMs > 5000 ? 'warn' : 'info';
114
+ this[level](`Performance: ${operation}`, {
115
+ operation,
116
+ durationMs,
117
+ ...context
118
+ });
119
+ }
120
+
121
+ /**
122
+ * Redact sensitive information from text
123
+ */
124
+ redact(text) {
125
+ if (typeof text !== 'string') return text;
126
+
127
+ const patterns = [
128
+ // Cloudflare tokens
129
+ [/(CLOUDFLARE_API_TOKEN=?)(\w{20,})/gi, '$1[REDACTED]'],
130
+ // Generic tokens
131
+ [/(token|api[_-]?key|auth[_-]?token)["']?[:=]\s*["']?([a-zA-Z0-9_-]{20,})["']?/gi, '$1: [REDACTED]'],
132
+ // Passwords
133
+ [/(password|passwd|pwd)["']?[:=]\s*["']?([^"'\s]{3,})["']?/gi, '$1: [REDACTED]'],
134
+ // Secrets
135
+ [/(secret|key)["']?[:=]\s*["']?([a-zA-Z0-9_-]{10,})["']?/gi, '$1: [REDACTED]'],
136
+ // Account/Zone IDs (partial)
137
+ [/(account[_-]?id|zone[_-]?id)["']?[:=]\s*["']?([a-zA-Z0-9]{8})([a-zA-Z0-9]{24,})["']?/gi, '$1: $2[REDACTED]']
138
+ ];
139
+
140
+ let redacted = text;
141
+ patterns.forEach(([pattern, replacement]) => {
142
+ redacted = redacted.replace(pattern, replacement);
143
+ });
144
+ return redacted;
145
+ }
146
+
147
+ /**
148
+ * Set log file for file output
149
+ */
150
+ setLogFile(filePath) {
151
+ this.logFile = filePath;
152
+ const dir = dirname(filePath);
153
+ if (!existsSync(dir)) {
154
+ mkdirSync(dir, { recursive: true });
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Private: Core logging implementation
160
+ */
161
+ _log(level, message, data = {}) {
162
+ const timestamp = new Date().toISOString();
163
+ const contextStr = Object.keys(this.context).length > 0
164
+ ? ` [${JSON.stringify(this.context)}]`
165
+ : '';
166
+
167
+ const logMessage = `[${timestamp}] ${level}${contextStr}: ${message}`;
168
+ const redactedMessage = this.redact(logMessage);
169
+
170
+ // Console output
171
+ const display = data && Object.keys(data).length > 0
172
+ ? `${redactedMessage} ${this.redact(JSON.stringify(data))}`
173
+ : redactedMessage;
174
+
175
+ console.log(display);
176
+
177
+ // File output
178
+ if (this.logFile) {
179
+ try {
180
+ const fileEntry = JSON.stringify({
181
+ timestamp,
182
+ level,
183
+ message: this.redact(message),
184
+ context: this.context,
185
+ data: this.redact(JSON.stringify(data))
186
+ }) + '\n';
187
+
188
+ appendFileSync(this.logFile, fileEntry);
189
+ } catch (error) {
190
+ console.error('Failed to write to log file:', error.message);
191
+ }
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Parse log level string to numeric value
197
+ */
198
+ _parseLogLevel(levelStr) {
199
+ const upper = levelStr.toUpperCase();
200
+ return LOG_LEVELS[upper] ?? LOG_LEVELS.INFO;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Export singleton logger
206
+ */
207
+ export const logger = new Logger({ framework: 'clodo' });
208
+
209
+ /**
210
+ * Backwards compatible factory function (for gradual migration)
211
+ */
212
+ export const createLogger = (prefix = 'ClodoFramework') => {
213
+ return new Logger({ prefix });
214
+ };
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { writeFile, appendFile, mkdir } from 'fs/promises';
7
7
  import { join } from 'path';
8
+ import { logger } from '../logging/Logger.js';
8
9
 
9
10
  export class ProductionMonitor {
10
11
  constructor(options = {}) {
@@ -104,18 +105,29 @@ export class ProductionMonitor {
104
105
  }
105
106
  };
106
107
 
107
- // Console output for development
108
- const consoleMethod = level === 'error' || level === 'fatal' ? 'error' :
109
- level === 'warn' ? 'warn' : 'log';
110
- console[consoleMethod](`[${level.toUpperCase()}] ${message}`, data);
108
+ // Use Logger for output
109
+ const methodMap = {
110
+ debug: 'debug',
111
+ info: 'info',
112
+ warn: 'warn',
113
+ error: 'error',
114
+ fatal: 'fatal'
115
+ };
116
+
117
+ const logMethod = methodMap[level] || 'info';
118
+ logger[logMethod](message, data);
111
119
 
112
- // File logging
120
+ // File logging through Logger
121
+ if (!this.config.logDir) {
122
+ this.config.logDir = 'logs';
123
+ }
113
124
  try {
114
125
  const logFile = join(this.config.logDir, `${new Date().toISOString().split('T')[0]}.log`);
115
- const logLine = JSON.stringify(logEntry) + '\n';
116
- await appendFile(logFile, logLine);
126
+ if (!logger.logFile) {
127
+ logger.setLogFile(logFile);
128
+ }
117
129
  } catch (error) {
118
- console.error('Failed to write log file:', error);
130
+ logger.error('Failed to set up log file', { error: error.message });
119
131
  }
120
132
 
121
133
  // Track errors for metrics
@@ -354,7 +366,7 @@ export class ProductionMonitor {
354
366
  const metricsData = this.getDetailedMetrics();
355
367
  await writeFile(metricsFile, JSON.stringify(metricsData, null, 2));
356
368
  } catch (error) {
357
- console.error('Failed to save metrics:', error);
369
+ logger.error('Failed to save metrics', { error: error.message });
358
370
  }
359
371
  }
360
372