@tamyla/clodo-framework 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 (130) hide show
  1. package/CHANGELOG.md +564 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1393 -0
  4. package/bin/README.md +71 -0
  5. package/bin/clodo-service.js +416 -0
  6. package/bin/security/security-cli.js +96 -0
  7. package/bin/service-management/README.md +74 -0
  8. package/bin/service-management/create-service.js +129 -0
  9. package/bin/service-management/init-service.js +102 -0
  10. package/bin/service-management/init-service.js.backup +889 -0
  11. package/bin/shared/config/customer-cli.js +293 -0
  12. package/dist/config/ConfigurationManager.js +159 -0
  13. package/dist/config/CustomerConfigCLI.js +220 -0
  14. package/dist/config/FeatureManager.js +426 -0
  15. package/dist/config/customers.js +441 -0
  16. package/dist/config/domains.js +180 -0
  17. package/dist/config/features.js +225 -0
  18. package/dist/config/index.js +6 -0
  19. package/dist/database/database-orchestrator.js +730 -0
  20. package/dist/database/index.js +4 -0
  21. package/dist/deployment/auditor.js +971 -0
  22. package/dist/deployment/index.js +10 -0
  23. package/dist/deployment/rollback-manager.js +523 -0
  24. package/dist/deployment/testers/api-tester.js +80 -0
  25. package/dist/deployment/testers/auth-tester.js +129 -0
  26. package/dist/deployment/testers/core.js +217 -0
  27. package/dist/deployment/testers/database-tester.js +105 -0
  28. package/dist/deployment/testers/index.js +74 -0
  29. package/dist/deployment/testers/load-tester.js +120 -0
  30. package/dist/deployment/testers/performance-tester.js +105 -0
  31. package/dist/deployment/validator.js +558 -0
  32. package/dist/deployment/wrangler-deployer.js +574 -0
  33. package/dist/handlers/GenericRouteHandler.js +532 -0
  34. package/dist/index.js +39 -0
  35. package/dist/migration/MigrationAdapters.js +562 -0
  36. package/dist/modules/ModuleManager.js +668 -0
  37. package/dist/modules/security.js +98 -0
  38. package/dist/orchestration/cross-domain-coordinator.js +1083 -0
  39. package/dist/orchestration/index.js +5 -0
  40. package/dist/orchestration/modules/DeploymentCoordinator.js +258 -0
  41. package/dist/orchestration/modules/DomainResolver.js +196 -0
  42. package/dist/orchestration/modules/StateManager.js +332 -0
  43. package/dist/orchestration/multi-domain-orchestrator.js +255 -0
  44. package/dist/routing/EnhancedRouter.js +158 -0
  45. package/dist/schema/SchemaManager.js +778 -0
  46. package/dist/security/ConfigurationValidator.js +490 -0
  47. package/dist/security/DeploymentManager.js +208 -0
  48. package/dist/security/SecretGenerator.js +142 -0
  49. package/dist/security/SecurityCLI.js +228 -0
  50. package/dist/security/index.js +51 -0
  51. package/dist/security/patterns/environment-rules.js +66 -0
  52. package/dist/security/patterns/insecure-patterns.js +21 -0
  53. package/dist/service-management/ConfirmationEngine.js +411 -0
  54. package/dist/service-management/ErrorTracker.js +294 -0
  55. package/dist/service-management/GenerationEngine.js +3109 -0
  56. package/dist/service-management/InputCollector.js +237 -0
  57. package/dist/service-management/ServiceCreator.js +229 -0
  58. package/dist/service-management/ServiceInitializer.js +448 -0
  59. package/dist/service-management/ServiceOrchestrator.js +638 -0
  60. package/dist/service-management/handlers/ConfigMutator.js +130 -0
  61. package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
  62. package/dist/service-management/handlers/GenerationHandler.js +80 -0
  63. package/dist/service-management/handlers/InputHandler.js +59 -0
  64. package/dist/service-management/handlers/ValidationHandler.js +203 -0
  65. package/dist/service-management/index.js +7 -0
  66. package/dist/services/GenericDataService.js +488 -0
  67. package/dist/shared/cloudflare/domain-discovery.js +562 -0
  68. package/dist/shared/cloudflare/domain-manager.js +912 -0
  69. package/dist/shared/cloudflare/index.js +8 -0
  70. package/dist/shared/cloudflare/ops.js +387 -0
  71. package/dist/shared/config/cache.js +1167 -0
  72. package/dist/shared/config/command-config-manager.js +174 -0
  73. package/dist/shared/config/customer-cli.js +258 -0
  74. package/dist/shared/config/index.js +9 -0
  75. package/dist/shared/config/manager.js +289 -0
  76. package/dist/shared/database/connection-manager.js +338 -0
  77. package/dist/shared/database/index.js +7 -0
  78. package/dist/shared/database/orchestrator.js +632 -0
  79. package/dist/shared/deployment/auditor.js +971 -0
  80. package/dist/shared/deployment/index.js +10 -0
  81. package/dist/shared/deployment/rollback-manager.js +523 -0
  82. package/dist/shared/deployment/validator.js +558 -0
  83. package/dist/shared/index.js +32 -0
  84. package/dist/shared/monitoring/health-checker.js +250 -0
  85. package/dist/shared/monitoring/index.js +8 -0
  86. package/dist/shared/monitoring/memory-manager.js +382 -0
  87. package/dist/shared/monitoring/production-monitor.js +390 -0
  88. package/dist/shared/production-tester/api-tester.js +80 -0
  89. package/dist/shared/production-tester/auth-tester.js +129 -0
  90. package/dist/shared/production-tester/core.js +217 -0
  91. package/dist/shared/production-tester/database-tester.js +105 -0
  92. package/dist/shared/production-tester/index.js +74 -0
  93. package/dist/shared/production-tester/load-tester.js +120 -0
  94. package/dist/shared/production-tester/performance-tester.js +105 -0
  95. package/dist/shared/security/api-token-manager.js +296 -0
  96. package/dist/shared/security/index.js +8 -0
  97. package/dist/shared/security/secret-generator.js +918 -0
  98. package/dist/shared/security/secure-token-manager.js +379 -0
  99. package/dist/shared/utils/error-recovery.js +240 -0
  100. package/dist/shared/utils/graceful-shutdown-manager.js +380 -0
  101. package/dist/shared/utils/index.js +9 -0
  102. package/dist/shared/utils/interactive-prompts.js +134 -0
  103. package/dist/shared/utils/rate-limiter.js +249 -0
  104. package/dist/utils/ErrorHandler.js +173 -0
  105. package/dist/utils/deployment/config-cache.js +1160 -0
  106. package/dist/utils/deployment/index.js +6 -0
  107. package/dist/utils/deployment/interactive-prompts.js +97 -0
  108. package/dist/utils/deployment/secret-generator.js +896 -0
  109. package/dist/utils/dirname-helper.js +35 -0
  110. package/dist/utils/domain-config.js +159 -0
  111. package/dist/utils/error-recovery.js +240 -0
  112. package/dist/utils/esm-helper.js +52 -0
  113. package/dist/utils/framework-config.js +481 -0
  114. package/dist/utils/graceful-shutdown-manager.js +379 -0
  115. package/dist/utils/health-checker.js +114 -0
  116. package/dist/utils/index.js +36 -0
  117. package/dist/utils/prompt-handler.js +98 -0
  118. package/dist/utils/usage-tracker.js +252 -0
  119. package/dist/utils/validation.js +112 -0
  120. package/dist/version/VersionDetector.js +723 -0
  121. package/dist/worker/index.js +4 -0
  122. package/dist/worker/integration.js +332 -0
  123. package/docs/FRAMEWORK-ARCHITECTURE-OVERVIEW.md +206 -0
  124. package/docs/INTEGRATION_GUIDE.md +2045 -0
  125. package/docs/README.md +82 -0
  126. package/docs/SECURITY.md +242 -0
  127. package/docs/deployment/deployment-guide.md +540 -0
  128. package/docs/overview.md +280 -0
  129. package/package.json +176 -0
  130. package/types/index.d.ts +575 -0
@@ -0,0 +1,481 @@
1
+ /**
2
+ * Enhanced Configuration Manager
3
+ * Centralized configuration loading and management for the Clodo Framework
4
+ *
5
+ * Replaces hardcoded values throughout the codebase with configurable settings
6
+ * from validation-config.json and environment variables
7
+ */
8
+
9
+ import { readFileSync, existsSync } from 'fs';
10
+ import { join, dirname } from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ export class FrameworkConfig {
13
+ constructor(configPath = null) {
14
+ this.configPath = configPath || this.findConfigFile();
15
+ this.config = this.loadConfig();
16
+ this.environment = process.env.ENVIRONMENT || 'development';
17
+
18
+ // Validate environment variables on initialization
19
+ this.validateEnvironmentVariables();
20
+ }
21
+
22
+ /**
23
+ * Find the configuration file in standard locations
24
+ */
25
+ findConfigFile() {
26
+ let __filename, __dirname;
27
+
28
+ // Handle test environment where import.meta might be transformed
29
+ try {
30
+ __filename = fileURLToPath(import.meta.url);
31
+ __dirname = dirname(__filename);
32
+ } catch (error) {
33
+ // Fallback for test environment
34
+ __dirname = process.cwd();
35
+ __filename = join(__dirname, 'src', 'utils', 'framework-config.js');
36
+ }
37
+ const possiblePaths = ['./validation-config.json', '../validation-config.json', '../../validation-config.json', join(process.cwd(), 'validation-config.json'), join(__dirname, '..', '..', 'validation-config.json')];
38
+ for (const path of possiblePaths) {
39
+ if (existsSync(path)) {
40
+ return path;
41
+ }
42
+ }
43
+
44
+ // Return null instead of throwing - will use default config
45
+ console.warn('⚠️ validation-config.json not found. Using default configuration values.');
46
+ return null;
47
+ }
48
+
49
+ /**
50
+ * Load and parse the configuration file
51
+ */
52
+ loadConfig() {
53
+ // If no config file found, return default configuration
54
+ if (!this.configPath) {
55
+ console.log('📋 Using default framework configuration');
56
+ return this.getDefaultConfig();
57
+ }
58
+ try {
59
+ const configContent = readFileSync(this.configPath, 'utf8');
60
+ const config = JSON.parse(configContent);
61
+ console.log(`📋 Loaded configuration from: ${this.configPath}`);
62
+ return config;
63
+ } catch (error) {
64
+ console.warn(`⚠️ Failed to load configuration from ${this.configPath}: ${error.message}`);
65
+ console.log('📋 Falling back to default configuration');
66
+ return this.getDefaultConfig();
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Get default configuration when validation-config.json is not available
72
+ */
73
+ getDefaultConfig() {
74
+ return {
75
+ // Timing configuration (all in milliseconds)
76
+ deploymentTimeout: 30000,
77
+ retryAttempts: 3,
78
+ retryDelay: 1000,
79
+ connectionTimeout: 5000,
80
+ heartbeatInterval: 5000,
81
+ shutdownTimeout: 10000,
82
+ backupTimeout: 15000,
83
+ restoreTimeout: 20000,
84
+ migrationTimeout: 25000,
85
+ validationTimeout: 8000,
86
+ rollbackTimeout: 12000,
87
+ healthCheckInterval: 30000,
88
+ auditInterval: 60000,
89
+ cleanupInterval: 300000,
90
+ monitoringInterval: 15000,
91
+ alertThrottle: 5000,
92
+ // Network configuration
93
+ networking: {
94
+ maxConcurrentConnections: 10,
95
+ connectionPoolSize: 5,
96
+ requestTimeout: 30000,
97
+ maxRetries: 3,
98
+ retryDelay: 1000
99
+ },
100
+ // Database configuration
101
+ database: {
102
+ connectionTimeout: 10000,
103
+ queryTimeout: 30000,
104
+ transactionTimeout: 60000,
105
+ poolMin: 2,
106
+ poolMax: 10,
107
+ acquireTimeoutMillis: 60000,
108
+ createTimeoutMillis: 30000,
109
+ destroyTimeoutMillis: 5000,
110
+ idleTimeoutMillis: 30000,
111
+ reapIntervalMillis: 1000,
112
+ createRetryIntervalMillis: 200
113
+ },
114
+ // Environment configuration
115
+ environments: {
116
+ development: {
117
+ logLevel: 'debug',
118
+ debugMode: true,
119
+ dryRun: false
120
+ },
121
+ staging: {
122
+ logLevel: 'info',
123
+ debugMode: false,
124
+ dryRun: false
125
+ },
126
+ production: {
127
+ logLevel: 'warn',
128
+ debugMode: false,
129
+ dryRun: false
130
+ }
131
+ },
132
+ // Path configuration - all generated files go under generated/
133
+ paths: {
134
+ // Base generated directory
135
+ generated: process.env.FRAMEWORK_GENERATED_DIR || 'generated',
136
+ // Specific generated subdirectories
137
+ logs: process.env.FRAMEWORK_LOGS_DIR || 'generated/logs',
138
+ auditLogs: process.env.FRAMEWORK_AUDIT_DIR || 'generated/audit/logs',
139
+ backups: process.env.FRAMEWORK_BACKUP_DIR || 'generated/backups',
140
+ configCache: process.env.FRAMEWORK_CONFIG_CACHE_DIR || 'generated/cache/config',
141
+ secureTokens: process.env.FRAMEWORK_TOKEN_DIR || 'generated/cache/tokens',
142
+ auditReports: process.env.FRAMEWORK_REPORTS_DIR || 'generated/audit/reports',
143
+ testResults: process.env.FRAMEWORK_TEST_RESULTS_DIR || 'generated/test-results',
144
+ services: process.env.FRAMEWORK_SERVICES_DIR || 'generated/services',
145
+ temp: process.env.FRAMEWORK_TEMP_DIR || 'generated/temp'
146
+ }
147
+ };
148
+ }
149
+
150
+ /**
151
+ * Reload the configuration from file (useful for testing)
152
+ */
153
+ reload() {
154
+ this.config = this.loadConfig();
155
+ }
156
+
157
+ /**
158
+ * Get timing configuration with environment variable overrides
159
+ */
160
+ getTiming() {
161
+ const timing = this.config.timing || {};
162
+ return {
163
+ deploymentTimeout: parseInt(process.env.DEPLOYMENT_TIMEOUT) || timing.deploymentTimeout || 300000,
164
+ discoveryTimeout: parseInt(process.env.DISCOVERY_TIMEOUT) || timing.discoveryTimeout || 30000,
165
+ healthCheckTimeout: parseInt(process.env.HEALTH_CHECK_TIMEOUT) || timing.healthCheckTimeout || 10000,
166
+ productionTestTimeout: parseInt(process.env.PRODUCTION_TEST_TIMEOUT) || timing.productionTestTimeout || 30000,
167
+ shutdownTimeout: parseInt(process.env.SHUTDOWN_TIMEOUT) || timing.shutdownTimeout || 30000,
168
+ forceShutdownTimeout: parseInt(process.env.FORCE_SHUTDOWN_TIMEOUT) || timing.forceShutdownTimeout || 5000,
169
+ retryDelay: parseInt(process.env.RETRY_DELAY) || timing.retryDelay || 1000,
170
+ retryAttempts: parseInt(process.env.RETRY_ATTEMPTS) || timing.retryAttempts || 3,
171
+ cacheTTL: parseInt(process.env.CACHE_TTL) || timing.cacheTTL || 3600000,
172
+ maxAge: parseInt(process.env.MAX_AGE) || timing.maxAge || 86400000,
173
+ rateLimitWindow: parseInt(process.env.RATE_LIMIT_WINDOW) || timing.rateLimitWindow || 60000,
174
+ circuitBreakerTimeout: parseInt(process.env.CIRCUIT_BREAKER_TIMEOUT) || timing.circuitBreakerTimeout || 60000,
175
+ circuitBreakerThreshold: parseInt(process.env.CIRCUIT_BREAKER_THRESHOLD) || timing.circuitBreakerThreshold || 5,
176
+ deploymentInterval: parseInt(process.env.DEPLOYMENT_INTERVAL) || timing.deploymentInterval || 5000,
177
+ endpointValidationTimeout: parseInt(process.env.ENDPOINT_VALIDATION_TIMEOUT) || timing.endpointValidationTimeout || 5000,
178
+ maxConcurrentDeployments: parseInt(process.env.MAX_CONCURRENT_DEPLOYMENTS) || timing.maxConcurrentDeployments || 3
179
+ };
180
+ }
181
+
182
+ /**
183
+ * Get networking configuration
184
+ */
185
+ getNetworking() {
186
+ const networking = this.config.networking || {};
187
+ return {
188
+ endpoints: networking.endpoints || {},
189
+ development: networking.development || {},
190
+ rateLimiting: {
191
+ defaultRequests: parseInt(process.env.RATE_LIMIT_REQUESTS) || networking.rateLimiting?.defaultRequests || 100,
192
+ defaultWindow: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || networking.rateLimiting?.defaultWindow || 60000,
193
+ burstLimit: parseInt(process.env.RATE_LIMIT_BURST) || networking.rateLimiting?.burstLimit || 200,
194
+ strictMode: process.env.RATE_LIMIT_STRICT === 'true' || networking.rateLimiting?.strictMode || false
195
+ }
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Get database naming configuration
201
+ */
202
+ getDatabaseConfig() {
203
+ const database = this.config.database || {};
204
+ const naming = database.namingConvention || {};
205
+ return {
206
+ naming: {
207
+ development: naming.development || '{service}-dev',
208
+ staging: naming.staging || '{service}-staging',
209
+ production: naming.production || '{service}'
210
+ },
211
+ migration: database.migration || {},
212
+ connection: {
213
+ timeout: parseInt(process.env.DB_TIMEOUT) || database.connection?.timeout || 30000,
214
+ retryAttempts: parseInt(process.env.DB_RETRY_ATTEMPTS) || database.connection?.retryAttempts || 3,
215
+ poolSize: parseInt(process.env.DB_POOL_SIZE) || database.connection?.poolSize || 10
216
+ }
217
+ };
218
+ }
219
+
220
+ /**
221
+ * Get development ports configuration
222
+ */
223
+ getDevelopmentPorts() {
224
+ const networking = this.config.networking || {};
225
+ const development = networking.development || {};
226
+ const defaultPorts = development.defaultPorts || {};
227
+ return {
228
+ frontend: parseInt(process.env.FRONTEND_PORT) || defaultPorts.frontend || 3000,
229
+ api: parseInt(process.env.API_PORT) || defaultPorts.api || 8787,
230
+ worker: parseInt(process.env.WORKER_PORT) || defaultPorts.worker || 8787,
231
+ preview: parseInt(process.env.PREVIEW_PORT) || defaultPorts.preview || 8788
232
+ };
233
+ }
234
+
235
+ /**
236
+ * Get caching configuration
237
+ */
238
+ getCaching() {
239
+ const caching = this.config.caching || {};
240
+ return {
241
+ maxCacheSize: parseInt(process.env.MAX_CACHE_SIZE) || caching.maxCacheSize || 52428800,
242
+ compressionThreshold: parseInt(process.env.COMPRESSION_THRESHOLD) || caching.compressionThreshold || 1024,
243
+ cleanupInterval: parseInt(process.env.CLEANUP_INTERVAL) || caching.cleanupInterval || 3600000,
244
+ enableCompression: process.env.ENABLE_COMPRESSION === 'true' || caching.enableCompression || true,
245
+ maxEntries: parseInt(process.env.MAX_CACHE_ENTRIES) || caching.maxEntries || 1000
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Get monitoring configuration
251
+ */
252
+ getMonitoring() {
253
+ const monitoring = this.config.monitoring || {};
254
+ return {
255
+ healthCheck: monitoring.healthCheck || {},
256
+ metrics: monitoring.metrics || {},
257
+ logging: monitoring.logging || {}
258
+ };
259
+ }
260
+
261
+ /**
262
+ * Get security configuration
263
+ */
264
+ getSecurity() {
265
+ const security = this.config.security || {};
266
+ return {
267
+ requiredEnvironmentVars: security.requiredEnvironmentVars || [],
268
+ optionalEnvironmentVars: security.optionalEnvironmentVars || [],
269
+ secretsConfig: security.secretsConfig || {}
270
+ };
271
+ }
272
+
273
+ /**
274
+ * Get path configuration with environment variable overrides
275
+ * All generated files are organized under the generated/ folder by default
276
+ */
277
+ getPaths() {
278
+ const paths = this.config.paths || {};
279
+ return {
280
+ // Base generated directory
281
+ generated: process.env.FRAMEWORK_GENERATED_DIR || paths.generated || 'generated',
282
+ // Specific generated subdirectories
283
+ logs: process.env.FRAMEWORK_LOGS_DIR || paths.logs || 'generated/logs',
284
+ auditLogs: process.env.FRAMEWORK_AUDIT_DIR || paths.auditLogs || 'generated/audit/logs',
285
+ backups: process.env.FRAMEWORK_BACKUP_DIR || paths.backups || 'generated/backups',
286
+ configCache: process.env.FRAMEWORK_CONFIG_CACHE_DIR || paths.configCache || 'generated/cache/config',
287
+ secureTokens: process.env.FRAMEWORK_TOKEN_DIR || paths.secureTokens || 'generated/cache/tokens',
288
+ auditReports: process.env.FRAMEWORK_REPORTS_DIR || paths.auditReports || 'generated/audit/reports',
289
+ testResults: process.env.FRAMEWORK_TEST_RESULTS_DIR || paths.testResults || 'generated/test-results',
290
+ services: process.env.FRAMEWORK_SERVICES_DIR || paths.services || 'generated/services',
291
+ temp: process.env.FRAMEWORK_TEMP_DIR || paths.temp || 'generated/temp'
292
+ };
293
+ }
294
+
295
+ /**
296
+ * Get a clean command for removing all generated files
297
+ */
298
+ getCleanupCommand() {
299
+ const paths = this.getPaths();
300
+ return `rm -rf ${paths.generated}`;
301
+ }
302
+
303
+ /**
304
+ * Get environment configuration with validation
305
+ */
306
+ getEnvironmentConfig(environment = null) {
307
+ const env = environment || this.environment;
308
+ const environments = this.config.environments || {};
309
+ const envConfig = environments[env] || environments.development || {};
310
+ if (!envConfig || Object.keys(envConfig).length === 0) {
311
+ console.warn(`⚠️ No configuration found for environment: ${env}. Using development defaults.`);
312
+ return {
313
+ domainTemplate: process.env.DOMAIN_TEMPLATE || '{service}.{domain}',
314
+ workerSuffix: process.env.WORKER_SUFFIX || '',
315
+ databaseSuffix: process.env.DATABASE_SUFFIX || '',
316
+ logLevel: this.validateLogLevel(process.env.LOG_LEVEL) || 'info',
317
+ enableMetrics: process.env.ENABLE_METRICS === 'true' || true,
318
+ strictValidation: process.env.STRICT_VALIDATION === 'true' || false,
319
+ debugMode: env === 'development',
320
+ dryRun: false
321
+ };
322
+ }
323
+ return {
324
+ domainTemplate: process.env.DOMAIN_TEMPLATE || envConfig.domainTemplate || '{service}.{domain}',
325
+ workerSuffix: process.env.WORKER_SUFFIX || envConfig.workerSuffix || '',
326
+ databaseSuffix: process.env.DATABASE_SUFFIX || envConfig.databaseSuffix || '',
327
+ logLevel: this.validateLogLevel(process.env.LOG_LEVEL) || this.validateLogLevel(envConfig.logLevel) || 'info',
328
+ enableMetrics: process.env.ENABLE_METRICS === 'true' || envConfig.enableMetrics || true,
329
+ strictValidation: process.env.STRICT_VALIDATION === 'true' || envConfig.strictValidation || false,
330
+ debugMode: envConfig.debugMode || false,
331
+ dryRun: envConfig.dryRun || false
332
+ };
333
+ }
334
+
335
+ /**
336
+ * Validate LOG_LEVEL environment variable
337
+ */
338
+ validateLogLevel(level) {
339
+ const validLevels = ['error', 'warn', 'info', 'debug', 'trace'];
340
+ if (!level) return null;
341
+ const normalizedLevel = level.toLowerCase();
342
+ if (!validLevels.includes(normalizedLevel)) {
343
+ console.warn(`⚠️ Invalid LOG_LEVEL "${level}". Valid values: ${validLevels.join(', ')}. Using 'info'.`);
344
+ return 'info';
345
+ }
346
+ return normalizedLevel;
347
+ }
348
+
349
+ /**
350
+ * Validate required environment variables
351
+ */
352
+ validateEnvironmentVariables() {
353
+ const errors = [];
354
+ const warnings = [];
355
+
356
+ // Validate LOG_LEVEL if present
357
+ if (process.env.LOG_LEVEL) {
358
+ this.validateLogLevel(process.env.LOG_LEVEL);
359
+ }
360
+
361
+ // Validate ENVIRONMENT if present
362
+ if (process.env.ENVIRONMENT) {
363
+ const validEnvironments = ['development', 'staging', 'production'];
364
+ if (!validEnvironments.includes(process.env.ENVIRONMENT)) {
365
+ warnings.push(`Invalid ENVIRONMENT "${process.env.ENVIRONMENT}". Valid values: ${validEnvironments.join(', ')}`);
366
+ }
367
+ }
368
+
369
+ // Validate framework-specific environment variables
370
+ const frameworkEnvVars = ['FRAMEWORK_LOGS_DIR', 'FRAMEWORK_AUDIT_DIR', 'FRAMEWORK_BACKUP_DIR', 'FRAMEWORK_CONFIG_CACHE_DIR', 'FRAMEWORK_TOKEN_DIR', 'FRAMEWORK_REPORTS_DIR'];
371
+ frameworkEnvVars.forEach(varName => {
372
+ if (process.env[varName]) {
373
+ // Validate path doesn't contain dangerous characters
374
+ const value = process.env[varName];
375
+ if (value.includes('..') || value.includes('~')) {
376
+ warnings.push(`Environment variable ${varName} contains potentially dangerous path: ${value}`);
377
+ }
378
+ }
379
+ });
380
+
381
+ // Log validation results
382
+ if (warnings.length > 0) {
383
+ console.warn('⚠️ Environment variable validation warnings:');
384
+ warnings.forEach(warning => console.warn(` - ${warning}`));
385
+ }
386
+ if (errors.length > 0) {
387
+ console.error('❌ Environment variable validation errors:');
388
+ errors.forEach(error => console.error(` - ${error}`));
389
+ throw new Error('Environment variable validation failed');
390
+ }
391
+ if (warnings.length === 0 && errors.length === 0) {
392
+ console.log('✅ Environment variables validated successfully');
393
+ }
394
+ return {
395
+ errors,
396
+ warnings
397
+ };
398
+ }
399
+
400
+ /**
401
+ * Get testing configuration
402
+ */
403
+ getTesting() {
404
+ const testing = this.config.testing || {};
405
+ return {
406
+ production: {
407
+ enabled: process.env.PRODUCTION_TESTS === 'true' || testing.production?.enabled || true,
408
+ lightweight: process.env.LIGHTWEIGHT_TESTS === 'true' || testing.production?.lightweight || true,
409
+ skipHeavyTests: process.env.SKIP_HEAVY_TESTS === 'true' || testing.production?.skipHeavyTests || true,
410
+ generateReports: process.env.GENERATE_REPORTS === 'true' || testing.production?.generateReports || false,
411
+ testTimeout: parseInt(process.env.TEST_TIMEOUT) || testing.production?.testTimeout || 30000
412
+ },
413
+ integration: testing.integration || {}
414
+ };
415
+ }
416
+
417
+ /**
418
+ * Generate database name based on service and environment
419
+ */
420
+ generateDatabaseName(serviceName, environment = this.environment) {
421
+ const dbConfig = this.getDatabaseConfig();
422
+ const template = dbConfig.naming[environment] || dbConfig.naming.production || '{service}';
423
+ return template.replace('{service}', serviceName);
424
+ }
425
+
426
+ /**
427
+ * Generate development URLs based on service and configuration
428
+ */
429
+ generateDevelopmentUrls(serviceName) {
430
+ const ports = this.getDevelopmentPorts();
431
+ return {
432
+ frontend: `http://localhost:${ports.frontend}`,
433
+ api: `http://localhost:${ports.api}`,
434
+ worker: `http://localhost:${ports.worker}`,
435
+ preview: `http://localhost:${ports.preview}`
436
+ };
437
+ }
438
+
439
+ /**
440
+ * Validate environment variables
441
+ */
442
+ validateEnvironment() {
443
+ const security = this.getSecurity();
444
+ const missing = [];
445
+ for (const envVar of security.requiredEnvironmentVars) {
446
+ if (!process.env[envVar]) {
447
+ missing.push(envVar);
448
+ }
449
+ }
450
+ if (missing.length > 0) {
451
+ throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
452
+ }
453
+ return true;
454
+ }
455
+
456
+ /**
457
+ * Get all configuration for easy access
458
+ */
459
+ getAll() {
460
+ return {
461
+ timing: this.getTiming(),
462
+ networking: this.getNetworking(),
463
+ environment: this.getEnvironmentConfig(),
464
+ database: this.getDatabaseConfig(),
465
+ ports: this.getDevelopmentPorts(),
466
+ caching: this.getCaching(),
467
+ monitoring: this.getMonitoring(),
468
+ security: this.getSecurity(),
469
+ testing: this.getTesting()
470
+ };
471
+ }
472
+ }
473
+
474
+ // Export singleton instance for easy access
475
+ export const frameworkConfig = new FrameworkConfig();
476
+
477
+ // Export utility functions
478
+ export const getFrameworkConfig = (configPath = null) => {
479
+ return configPath ? new FrameworkConfig(configPath) : frameworkConfig;
480
+ };
481
+ export default FrameworkConfig;