@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.
- package/CHANGELOG.md +564 -0
- package/LICENSE +21 -0
- package/README.md +1393 -0
- package/bin/README.md +71 -0
- package/bin/clodo-service.js +416 -0
- package/bin/security/security-cli.js +96 -0
- package/bin/service-management/README.md +74 -0
- package/bin/service-management/create-service.js +129 -0
- package/bin/service-management/init-service.js +102 -0
- package/bin/service-management/init-service.js.backup +889 -0
- package/bin/shared/config/customer-cli.js +293 -0
- package/dist/config/ConfigurationManager.js +159 -0
- package/dist/config/CustomerConfigCLI.js +220 -0
- package/dist/config/FeatureManager.js +426 -0
- package/dist/config/customers.js +441 -0
- package/dist/config/domains.js +180 -0
- package/dist/config/features.js +225 -0
- package/dist/config/index.js +6 -0
- package/dist/database/database-orchestrator.js +730 -0
- package/dist/database/index.js +4 -0
- package/dist/deployment/auditor.js +971 -0
- package/dist/deployment/index.js +10 -0
- package/dist/deployment/rollback-manager.js +523 -0
- package/dist/deployment/testers/api-tester.js +80 -0
- package/dist/deployment/testers/auth-tester.js +129 -0
- package/dist/deployment/testers/core.js +217 -0
- package/dist/deployment/testers/database-tester.js +105 -0
- package/dist/deployment/testers/index.js +74 -0
- package/dist/deployment/testers/load-tester.js +120 -0
- package/dist/deployment/testers/performance-tester.js +105 -0
- package/dist/deployment/validator.js +558 -0
- package/dist/deployment/wrangler-deployer.js +574 -0
- package/dist/handlers/GenericRouteHandler.js +532 -0
- package/dist/index.js +39 -0
- package/dist/migration/MigrationAdapters.js +562 -0
- package/dist/modules/ModuleManager.js +668 -0
- package/dist/modules/security.js +98 -0
- package/dist/orchestration/cross-domain-coordinator.js +1083 -0
- package/dist/orchestration/index.js +5 -0
- package/dist/orchestration/modules/DeploymentCoordinator.js +258 -0
- package/dist/orchestration/modules/DomainResolver.js +196 -0
- package/dist/orchestration/modules/StateManager.js +332 -0
- package/dist/orchestration/multi-domain-orchestrator.js +255 -0
- package/dist/routing/EnhancedRouter.js +158 -0
- package/dist/schema/SchemaManager.js +778 -0
- package/dist/security/ConfigurationValidator.js +490 -0
- package/dist/security/DeploymentManager.js +208 -0
- package/dist/security/SecretGenerator.js +142 -0
- package/dist/security/SecurityCLI.js +228 -0
- package/dist/security/index.js +51 -0
- package/dist/security/patterns/environment-rules.js +66 -0
- package/dist/security/patterns/insecure-patterns.js +21 -0
- package/dist/service-management/ConfirmationEngine.js +411 -0
- package/dist/service-management/ErrorTracker.js +294 -0
- package/dist/service-management/GenerationEngine.js +3109 -0
- package/dist/service-management/InputCollector.js +237 -0
- package/dist/service-management/ServiceCreator.js +229 -0
- package/dist/service-management/ServiceInitializer.js +448 -0
- package/dist/service-management/ServiceOrchestrator.js +638 -0
- package/dist/service-management/handlers/ConfigMutator.js +130 -0
- package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
- package/dist/service-management/handlers/GenerationHandler.js +80 -0
- package/dist/service-management/handlers/InputHandler.js +59 -0
- package/dist/service-management/handlers/ValidationHandler.js +203 -0
- package/dist/service-management/index.js +7 -0
- package/dist/services/GenericDataService.js +488 -0
- package/dist/shared/cloudflare/domain-discovery.js +562 -0
- package/dist/shared/cloudflare/domain-manager.js +912 -0
- package/dist/shared/cloudflare/index.js +8 -0
- package/dist/shared/cloudflare/ops.js +387 -0
- package/dist/shared/config/cache.js +1167 -0
- package/dist/shared/config/command-config-manager.js +174 -0
- package/dist/shared/config/customer-cli.js +258 -0
- package/dist/shared/config/index.js +9 -0
- package/dist/shared/config/manager.js +289 -0
- package/dist/shared/database/connection-manager.js +338 -0
- package/dist/shared/database/index.js +7 -0
- package/dist/shared/database/orchestrator.js +632 -0
- package/dist/shared/deployment/auditor.js +971 -0
- package/dist/shared/deployment/index.js +10 -0
- package/dist/shared/deployment/rollback-manager.js +523 -0
- package/dist/shared/deployment/validator.js +558 -0
- package/dist/shared/index.js +32 -0
- package/dist/shared/monitoring/health-checker.js +250 -0
- package/dist/shared/monitoring/index.js +8 -0
- package/dist/shared/monitoring/memory-manager.js +382 -0
- package/dist/shared/monitoring/production-monitor.js +390 -0
- package/dist/shared/production-tester/api-tester.js +80 -0
- package/dist/shared/production-tester/auth-tester.js +129 -0
- package/dist/shared/production-tester/core.js +217 -0
- package/dist/shared/production-tester/database-tester.js +105 -0
- package/dist/shared/production-tester/index.js +74 -0
- package/dist/shared/production-tester/load-tester.js +120 -0
- package/dist/shared/production-tester/performance-tester.js +105 -0
- package/dist/shared/security/api-token-manager.js +296 -0
- package/dist/shared/security/index.js +8 -0
- package/dist/shared/security/secret-generator.js +918 -0
- package/dist/shared/security/secure-token-manager.js +379 -0
- package/dist/shared/utils/error-recovery.js +240 -0
- package/dist/shared/utils/graceful-shutdown-manager.js +380 -0
- package/dist/shared/utils/index.js +9 -0
- package/dist/shared/utils/interactive-prompts.js +134 -0
- package/dist/shared/utils/rate-limiter.js +249 -0
- package/dist/utils/ErrorHandler.js +173 -0
- package/dist/utils/deployment/config-cache.js +1160 -0
- package/dist/utils/deployment/index.js +6 -0
- package/dist/utils/deployment/interactive-prompts.js +97 -0
- package/dist/utils/deployment/secret-generator.js +896 -0
- package/dist/utils/dirname-helper.js +35 -0
- package/dist/utils/domain-config.js +159 -0
- package/dist/utils/error-recovery.js +240 -0
- package/dist/utils/esm-helper.js +52 -0
- package/dist/utils/framework-config.js +481 -0
- package/dist/utils/graceful-shutdown-manager.js +379 -0
- package/dist/utils/health-checker.js +114 -0
- package/dist/utils/index.js +36 -0
- package/dist/utils/prompt-handler.js +98 -0
- package/dist/utils/usage-tracker.js +252 -0
- package/dist/utils/validation.js +112 -0
- package/dist/version/VersionDetector.js +723 -0
- package/dist/worker/index.js +4 -0
- package/dist/worker/integration.js +332 -0
- package/docs/FRAMEWORK-ARCHITECTURE-OVERVIEW.md +206 -0
- package/docs/INTEGRATION_GUIDE.md +2045 -0
- package/docs/README.md +82 -0
- package/docs/SECURITY.md +242 -0
- package/docs/deployment/deployment-guide.md +540 -0
- package/docs/overview.md +280 -0
- package/package.json +176 -0
- 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;
|