@tamyla/clodo-framework 3.1.10 → 3.1.11

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 (73) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/bin/clodo-service-old.js +2 -2
  3. package/dist/bin/commands/create.js +1 -1
  4. package/dist/bin/commands/diagnose.js +1 -1
  5. package/dist/bin/commands/update.js +1 -1
  6. package/dist/bin/commands/validate.js +1 -1
  7. package/dist/bin/database/enterprise-db-manager.js +3 -3
  8. package/dist/bin/deployment/enterprise-deploy.js +3 -3
  9. package/dist/bin/deployment/master-deploy.js +3 -3
  10. package/dist/bin/deployment/modular-enterprise-deploy.js +3 -3
  11. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +1 -1
  12. package/dist/bin/deployment/modules/EnvironmentManager.js +2 -2
  13. package/dist/bin/portfolio/portfolio-manager.js +3 -3
  14. package/dist/bin/security/security-cli.js +1 -1
  15. package/dist/bin/service-management/create-service.js +1 -1
  16. package/dist/bin/service-management/init-service.js +1 -1
  17. package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
  18. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  19. package/package.json +1 -6
  20. package/bin/README.md +0 -71
  21. package/bin/clodo-service.js +0 -72
  22. package/bin/database/README.md +0 -33
  23. package/bin/database/deployment-db-manager.js +0 -527
  24. package/bin/database/enterprise-db-manager.js +0 -738
  25. package/bin/database/wrangler-d1-manager.js +0 -775
  26. package/bin/security/security-cli.js +0 -117
  27. package/bin/service-management/README.md +0 -74
  28. package/bin/service-management/create-service.js +0 -129
  29. package/bin/service-management/init-service.js +0 -103
  30. package/bin/service-management/init-service.js.backup +0 -889
  31. package/bin/shared/cloudflare/domain-discovery.js +0 -637
  32. package/bin/shared/cloudflare/domain-manager.js +0 -952
  33. package/bin/shared/cloudflare/index.js +0 -8
  34. package/bin/shared/cloudflare/ops.js +0 -401
  35. package/bin/shared/config/ConfigurationManager.js +0 -539
  36. package/bin/shared/config/cache.js +0 -1230
  37. package/bin/shared/config/command-config-manager.js +0 -184
  38. package/bin/shared/config/index.js +0 -21
  39. package/bin/shared/config/manager.js +0 -315
  40. package/bin/shared/database/connection-manager.js +0 -374
  41. package/bin/shared/database/index.js +0 -7
  42. package/bin/shared/database/orchestrator.js +0 -727
  43. package/bin/shared/deployment/auditor.js +0 -970
  44. package/bin/shared/deployment/index.js +0 -10
  45. package/bin/shared/deployment/rollback-manager.js +0 -570
  46. package/bin/shared/deployment/validator.js +0 -779
  47. package/bin/shared/index.js +0 -32
  48. package/bin/shared/logging/Logger.js +0 -214
  49. package/bin/shared/monitoring/health-checker.js +0 -484
  50. package/bin/shared/monitoring/index.js +0 -8
  51. package/bin/shared/monitoring/memory-manager.js +0 -387
  52. package/bin/shared/monitoring/production-monitor.js +0 -403
  53. package/bin/shared/production-tester/api-tester.js +0 -82
  54. package/bin/shared/production-tester/auth-tester.js +0 -132
  55. package/bin/shared/production-tester/core.js +0 -197
  56. package/bin/shared/production-tester/database-tester.js +0 -109
  57. package/bin/shared/production-tester/index.js +0 -77
  58. package/bin/shared/production-tester/load-tester.js +0 -131
  59. package/bin/shared/production-tester/performance-tester.js +0 -103
  60. package/bin/shared/security/api-token-manager.js +0 -312
  61. package/bin/shared/security/index.js +0 -8
  62. package/bin/shared/security/secret-generator.js +0 -942
  63. package/bin/shared/security/secure-token-manager.js +0 -398
  64. package/bin/shared/utils/ErrorHandler.js +0 -675
  65. package/bin/shared/utils/error-recovery.js +0 -245
  66. package/bin/shared/utils/file-manager.js +0 -162
  67. package/bin/shared/utils/formatters.js +0 -247
  68. package/bin/shared/utils/graceful-shutdown-manager.js +0 -390
  69. package/bin/shared/utils/index.js +0 -19
  70. package/bin/shared/utils/interactive-prompts.js +0 -146
  71. package/bin/shared/utils/interactive-utils.js +0 -530
  72. package/bin/shared/utils/rate-limiter.js +0 -246
  73. package/bin/shared/validation/ValidationRegistry.js +0 -143
@@ -1,245 +0,0 @@
1
- /**
2
- * Error Recovery Module - UNIFIED
3
- * Implements circuit breakers, retries, and graceful degradation
4
- *
5
- * Consolidation: Oct 26, 2025 - Phase 3.2.3a
6
- *
7
- * Merged from:
8
- * - src/utils/error-recovery.js (225 lines)
9
- * - bin/shared/utils/error-recovery.js (225 lines - DUPLICATE)
10
- *
11
- * This is the canonical version. All imports should use this version.
12
- */
13
-
14
- export class ErrorRecoveryManager {
15
- constructor(options = {}) {
16
- this.options = options;
17
- this.config = null;
18
- this.circuitStates = new Map(); // service -> { failures, lastFailure, state }
19
- this.retryStates = new Map(); // operation -> retry count
20
- }
21
-
22
- /**
23
- * Initialize with framework configuration
24
- */
25
- async initialize() {
26
- // Import framework config for consistent timing and retry settings
27
- try {
28
- const { frameworkConfig } = await import('./framework-config.js');
29
- const timing = frameworkConfig.getTiming();
30
-
31
- this.config = {
32
- maxRetries: this.options.maxRetries || timing.retryAttempts,
33
- retryDelay: this.options.retryDelay || timing.retryDelay,
34
- circuitBreakerThreshold: this.options.circuitBreakerThreshold || timing.circuitBreakerThreshold,
35
- circuitBreakerTimeout: this.options.circuitBreakerTimeout || timing.circuitBreakerTimeout,
36
- gracefulDegradation: this.options.gracefulDegradation !== false,
37
- ...this.options
38
- };
39
- } catch (error) {
40
- // Fallback to defaults if framework config not available
41
- this.config = {
42
- maxRetries: this.options.maxRetries || 3,
43
- retryDelay: this.options.retryDelay || 1000,
44
- circuitBreakerThreshold: this.options.circuitBreakerThreshold || 5,
45
- circuitBreakerTimeout: this.options.circuitBreakerTimeout || 60000,
46
- gracefulDegradation: this.options.gracefulDegradation !== false,
47
- ...this.options
48
- };
49
- }
50
- }
51
-
52
- /**
53
- * Execute operation with error recovery
54
- */
55
- async executeWithRecovery(operation, options = {}) {
56
- const config = { ...this.config, ...options };
57
- const operationId = this.getOperationId(operation);
58
-
59
- // Check circuit breaker
60
- if (this.isCircuitOpen(operationId)) {
61
- if (config.gracefulDegradation) {
62
- return this.executeGracefulFallback(operation, config);
63
- }
64
- throw new Error(`Circuit breaker open for operation: ${operationId}`);
65
- }
66
-
67
- let lastError;
68
- for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
69
- try {
70
- const result = await operation();
71
- this.recordSuccess(operationId);
72
- return result;
73
- } catch (error) {
74
- lastError = error;
75
- this.recordFailure(operationId, error);
76
-
77
- if (attempt < config.maxRetries) {
78
- const delay = this.calculateRetryDelay(attempt, config.retryDelay);
79
- await this.delay(delay);
80
- }
81
- }
82
- }
83
-
84
- // All retries exhausted
85
- if (config.gracefulDegradation) {
86
- return this.executeGracefulFallback(operation, config);
87
- }
88
-
89
- throw lastError;
90
- }
91
-
92
- /**
93
- * Check if circuit breaker is open
94
- */
95
- isCircuitOpen(operationId) {
96
- const state = this.circuitStates.get(operationId);
97
- if (!state) return false;
98
-
99
- if (state.state === 'open') {
100
- // Check if timeout has passed
101
- if (Date.now() - state.lastFailure > this.config.circuitBreakerTimeout) {
102
- state.state = 'half-open';
103
- state.failures = 0;
104
- return false;
105
- }
106
- return true;
107
- }
108
-
109
- return false;
110
- }
111
-
112
- /**
113
- * Record operation success
114
- */
115
- recordSuccess(operationId) {
116
- const state = this.circuitStates.get(operationId);
117
- if (state) {
118
- if (state.state === 'half-open') {
119
- state.state = 'closed';
120
- state.failures = 0;
121
- }
122
- }
123
- }
124
-
125
- /**
126
- * Record operation failure
127
- */
128
- recordFailure(operationId, error) {
129
- let state = this.circuitStates.get(operationId);
130
- if (!state) {
131
- state = { failures: 0, lastFailure: 0, state: 'closed' };
132
- this.circuitStates.set(operationId, state);
133
- }
134
-
135
- state.failures++;
136
- state.lastFailure = Date.now();
137
-
138
- if (state.failures >= this.config.circuitBreakerThreshold) {
139
- state.state = 'open';
140
- }
141
- }
142
-
143
- /**
144
- * Calculate retry delay with exponential backoff
145
- */
146
- calculateRetryDelay(attempt, baseDelay) {
147
- const exponentialDelay = baseDelay * Math.pow(2, attempt);
148
- const jitter = Math.random() * 0.1 * exponentialDelay;
149
- return Math.min(exponentialDelay + jitter, 30000); // Max 30 seconds
150
- }
151
-
152
- /**
153
- * Execute graceful fallback
154
- */
155
- async executeGracefulFallback(operation, config) {
156
- console.warn(`Executing graceful fallback for operation`);
157
-
158
- // Try to execute with reduced functionality
159
- try {
160
- // For deployment operations, try a simplified version
161
- if (operation.name && operation.name.includes('deploy')) {
162
- return { success: false, degraded: true, message: 'Operation executed in degraded mode' };
163
- }
164
-
165
- // For data operations, return cached or default data
166
- if (operation.name && operation.name.includes('fetch')) {
167
- return { data: [], cached: true, degraded: true };
168
- }
169
-
170
- // Default fallback
171
- return { success: false, degraded: true, fallback: true };
172
-
173
- } catch (fallbackError) {
174
- console.error('Graceful fallback also failed:', fallbackError);
175
- throw fallbackError;
176
- }
177
- }
178
-
179
- /**
180
- * Get unique operation ID
181
- */
182
- getOperationId(operation) {
183
- if (typeof operation === 'function' && operation.name) {
184
- return operation.name;
185
- }
186
- return `operation_${Date.now()}_${Math.random()}`;
187
- }
188
-
189
- /**
190
- * Utility delay function
191
- */
192
- delay(ms) {
193
- return new Promise(resolve => setTimeout(resolve, ms));
194
- }
195
-
196
- /**
197
- * Get circuit breaker status
198
- */
199
- getCircuitStatus(operationId) {
200
- const state = this.circuitStates.get(operationId);
201
- if (!state) {
202
- return { state: 'closed', failures: 0 };
203
- }
204
- return {
205
- state: state.state,
206
- failures: state.failures,
207
- lastFailure: state.lastFailure,
208
- timeSinceLastFailure: Date.now() - state.lastFailure
209
- };
210
- }
211
-
212
- /**
213
- * Reset circuit breaker
214
- */
215
- resetCircuit(operationId) {
216
- this.circuitStates.delete(operationId);
217
- }
218
-
219
- /**
220
- * Get all circuit statuses
221
- */
222
- getAllCircuitStatuses() {
223
- const statuses = {};
224
- for (const [operationId, state] of this.circuitStates) {
225
- statuses[operationId] = this.getCircuitStatus(operationId);
226
- }
227
- return statuses;
228
- }
229
- }
230
-
231
- /**
232
- * Retry wrapper for functions
233
- */
234
- export function withRetry(fn, options = {}) {
235
- const recovery = new ErrorRecoveryManager(options);
236
- return (...args) => recovery.executeWithRecovery(() => fn(...args), options);
237
- }
238
-
239
- /**
240
- * Circuit breaker wrapper for functions
241
- */
242
- export function withCircuitBreaker(fn, options = {}) {
243
- const recovery = new ErrorRecoveryManager(options);
244
- return (...args) => recovery.executeWithRecovery(() => fn(...args), options);
245
- }
@@ -1,162 +0,0 @@
1
- /**
2
- * Centralized File Manager
3
- * Replaces: 12 scattered file operation implementations
4
- * Savings: 200+ lines
5
- */
6
-
7
- import {
8
- readFileSync, writeFileSync, appendFileSync,
9
- existsSync, mkdirSync, statSync
10
- } from 'fs';
11
- import { dirname, basename } from 'path';
12
-
13
- export class FileManager {
14
- constructor(options = {}) {
15
- this.cache = new Map();
16
- this.enableCache = options.enableCache !== false;
17
- this.createBackups = options.createBackups !== false;
18
- this.backupDir = options.backupDir || '.backups';
19
- }
20
-
21
- /**
22
- * Read JSON configuration file
23
- */
24
- readConfig(path, defaultValue = null) {
25
- try {
26
- if (this.enableCache && this.cache.has(path)) {
27
- return this.cache.get(path);
28
- }
29
-
30
- if (!existsSync(path)) {
31
- if (defaultValue !== null) return defaultValue;
32
- throw new Error(`Configuration file not found: ${path}`);
33
- }
34
-
35
- const content = readFileSync(path, 'utf8');
36
- const data = JSON.parse(content);
37
-
38
- if (this.enableCache) {
39
- this.cache.set(path, data);
40
- }
41
-
42
- return data;
43
- } catch (error) {
44
- if (error.message.includes('JSON')) {
45
- throw new Error(`Invalid JSON in configuration file: ${error.message}`);
46
- }
47
- throw error;
48
- }
49
- }
50
-
51
- /**
52
- * Write JSON configuration file with optional backup
53
- */
54
- writeConfig(path, data, options = {}) {
55
- try {
56
- // Create backup if needed
57
- if (this.createBackups && existsSync(path)) {
58
- this.createBackup(path);
59
- }
60
-
61
- // Ensure directory exists
62
- this.ensureDir(dirname(path));
63
-
64
- // Write file
65
- const content = JSON.stringify(data, null, 2);
66
- writeFileSync(path, content, 'utf8');
67
-
68
- // Clear cache
69
- if (this.enableCache) {
70
- this.cache.delete(path);
71
- }
72
-
73
- return { success: true, path };
74
- } catch (error) {
75
- throw new Error(`Failed to write configuration: ${error.message}`);
76
- }
77
- }
78
-
79
- /**
80
- * Read text file
81
- */
82
- readFile(path) {
83
- if (!existsSync(path)) {
84
- throw new Error(`File not found: ${path}`);
85
- }
86
- return readFileSync(path, 'utf8');
87
- }
88
-
89
- /**
90
- * Write text file
91
- */
92
- writeFile(path, content) {
93
- this.ensureDir(dirname(path));
94
- writeFileSync(path, content, 'utf8');
95
- }
96
-
97
- /**
98
- * Append to file
99
- */
100
- appendFile(path, content) {
101
- this.ensureDir(dirname(path));
102
- appendFileSync(path, content, 'utf8');
103
- }
104
-
105
- /**
106
- * Check if file exists
107
- */
108
- exists(path) {
109
- return existsSync(path);
110
- }
111
-
112
- /**
113
- * Ensure directory exists
114
- */
115
- ensureDir(dir) {
116
- if (!existsSync(dir)) {
117
- mkdirSync(dir, { recursive: true });
118
- }
119
- }
120
-
121
- /**
122
- * Create backup of file
123
- */
124
- createBackup(path) {
125
- this.ensureDir(this.backupDir);
126
-
127
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
128
- const fileName = basename(path);
129
- const backupPath = `${this.backupDir}/${fileName}.${timestamp}.bak`;
130
-
131
- const content = readFileSync(path, 'utf8');
132
- writeFileSync(backupPath, content, 'utf8');
133
-
134
- return backupPath;
135
- }
136
-
137
- /**
138
- * Get file stats
139
- */
140
- getStats(path) {
141
- if (!existsSync(path)) {
142
- return null;
143
- }
144
- return statSync(path);
145
- }
146
-
147
- /**
148
- * Clear cache
149
- */
150
- clearCache(path = null) {
151
- if (path) {
152
- this.cache.delete(path);
153
- } else {
154
- this.cache.clear();
155
- }
156
- }
157
- }
158
-
159
- /**
160
- * Export singleton instance
161
- */
162
- export const fileManager = new FileManager();
@@ -1,247 +0,0 @@
1
- /**
2
- * Data Formatters for Clodo Framework
3
- * Centralizes all data transformation logic
4
- * Replaces: 5 scattered formatting implementations
5
- * Savings: 150+ lines
6
- */
7
-
8
- /**
9
- * Name formatting utilities
10
- */
11
- export const NameFormatters = {
12
- /**
13
- * Convert kebab-case to Display Case
14
- * Example: 'my-service' → 'My Service'
15
- */
16
- toDisplayName(kebabCase) {
17
- if (!kebabCase) return '';
18
- return kebabCase
19
- .replace(/-/g, ' ')
20
- .replace(/\b\w/g, l => l.toUpperCase());
21
- },
22
-
23
- /**
24
- * Convert camelCase to kebab-case
25
- * Example: 'myService' → 'my-service'
26
- */
27
- toKebabCase(camelCase) {
28
- if (!camelCase) return '';
29
- return camelCase
30
- .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
31
- .replace(/^([A-Z])([A-Z])/g, '$1-$2')
32
- .toLowerCase();
33
- },
34
-
35
- /**
36
- * Convert kebab-case to camelCase
37
- * Example: 'my-service' → 'myService'
38
- */
39
- toCamelCase(kebabCase) {
40
- if (!kebabCase) return '';
41
- return kebabCase
42
- .split('-')
43
- .map((part, i) =>
44
- i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)
45
- )
46
- .join('');
47
- },
48
-
49
- /**
50
- * Convert snake_case to camelCase
51
- * Example: 'my_service' → 'myService'
52
- */
53
- snakeToCamel(snakeCase) {
54
- if (!snakeCase) return '';
55
- return snakeCase
56
- .split('_')
57
- .map((part, i) =>
58
- i === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1)
59
- )
60
- .join('');
61
- }
62
- };
63
-
64
- /**
65
- * URL formatting utilities
66
- */
67
- export const UrlFormatters = {
68
- /**
69
- * Build service URL
70
- * Example: buildServiceUrl('api', 'example.com', 'production')
71
- * → 'https://api.example.com'
72
- */
73
- buildServiceUrl(serviceName, domain, environment = 'production') {
74
- if (!serviceName || !domain) return '';
75
-
76
- const prefix = environment === 'production'
77
- ? serviceName
78
- : `${serviceName}-${environment.substring(0, 3)}`;
79
-
80
- return `https://${prefix}.${domain}`;
81
- },
82
-
83
- /**
84
- * Build production URL
85
- */
86
- buildProductionUrl(serviceName, domain) {
87
- return this.buildServiceUrl(serviceName, domain, 'production');
88
- },
89
-
90
- /**
91
- * Build staging URL
92
- */
93
- buildStagingUrl(serviceName, domain) {
94
- return this.buildServiceUrl(serviceName, domain, 'staging');
95
- },
96
-
97
- /**
98
- * Build development URL
99
- */
100
- buildDevUrl(serviceName, domain) {
101
- return this.buildServiceUrl(serviceName, domain, 'development');
102
- },
103
-
104
- /**
105
- * Build API endpoint URL
106
- */
107
- buildApiUrl(serviceName, domain, path = '') {
108
- const baseUrl = this.buildProductionUrl(serviceName, domain);
109
- return path ? `${baseUrl}${path}` : baseUrl;
110
- }
111
- };
112
-
113
- /**
114
- * Resource name formatters
115
- */
116
- export const ResourceFormatters = {
117
- /**
118
- * Format database name
119
- * Example: 'my-service' → 'my-service-db'
120
- */
121
- databaseName(serviceName) {
122
- if (!serviceName) return '';
123
- return `${serviceName}-db`;
124
- },
125
-
126
- /**
127
- * Format worker name
128
- * Example: 'my-service' → 'my-service-worker'
129
- */
130
- workerName(serviceName) {
131
- if (!serviceName) return '';
132
- return `${serviceName}-worker`;
133
- },
134
-
135
- /**
136
- * Format service directory
137
- * Example: 'my-service' → './services/my-service'
138
- */
139
- serviceDirectory(serviceName) {
140
- if (!serviceName) return '';
141
- return `./services/${serviceName}`;
142
- },
143
-
144
- /**
145
- * Format configuration key
146
- * Example: 'cloudflareApiToken' → 'cloudflare-api-token'
147
- */
148
- configKey(camelCase) {
149
- return NameFormatters.toKebabCase(camelCase);
150
- }
151
- };
152
-
153
- /**
154
- * Environment-related formatters
155
- */
156
- export const EnvironmentFormatters = {
157
- /**
158
- * Get environment variable prefix
159
- * Example: 'production' → 'PROD_'
160
- */
161
- getEnvPrefix(environment) {
162
- switch (environment) {
163
- case 'production':
164
- return 'PROD_';
165
- case 'staging':
166
- return 'STAGING_';
167
- case 'development':
168
- return 'DEV_';
169
- default:
170
- return 'APP_';
171
- }
172
- },
173
-
174
- /**
175
- * Get log level for environment
176
- * Example: 'production' → 'warn'
177
- */
178
- getLogLevel(environment) {
179
- switch (environment) {
180
- case 'production':
181
- return 'warn';
182
- case 'staging':
183
- return 'info';
184
- case 'development':
185
- return 'debug';
186
- default:
187
- return 'info';
188
- }
189
- },
190
-
191
- /**
192
- * Get CORS policy for environment
193
- */
194
- getCorsPolicy(domain, environment) {
195
- switch (environment) {
196
- case 'production':
197
- return `https://${domain}`;
198
- case 'staging':
199
- return `https://${domain}`;
200
- case 'development':
201
- return '*'; // Allow all in development
202
- default:
203
- return '*';
204
- }
205
- }
206
- };
207
-
208
- /**
209
- * Version formatting
210
- */
211
- export const VersionFormatters = {
212
- /**
213
- * Normalize version string
214
- */
215
- normalize(version) {
216
- const match = version.match(/(\d+\.\d+\.\d+)/);
217
- return match ? match[1] : '1.0.0';
218
- },
219
-
220
- /**
221
- * Bump version
222
- */
223
- bump(version, type = 'patch') {
224
- const [major, minor, patch] = version.split('.').map(Number);
225
-
226
- switch (type) {
227
- case 'major':
228
- return `${major + 1}.0.0`;
229
- case 'minor':
230
- return `${major}.${minor + 1}.0`;
231
- case 'patch':
232
- default:
233
- return `${major}.${minor}.${patch + 1}`;
234
- }
235
- }
236
- };
237
-
238
- /**
239
- * Convenience exports - combine all formatters
240
- */
241
- export const Formatters = {
242
- ...NameFormatters,
243
- ...UrlFormatters,
244
- ...ResourceFormatters,
245
- ...EnvironmentFormatters,
246
- ...VersionFormatters
247
- };