@tamyla/clodo-framework 3.1.9 → 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 (75) hide show
  1. package/CHANGELOG.md +14 -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 +4 -4
  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/config/index.js +1 -1
  19. package/dist/bin/shared/deployment/index.js +2 -2
  20. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  21. package/package.json +1 -6
  22. package/bin/README.md +0 -71
  23. package/bin/clodo-service.js +0 -72
  24. package/bin/database/README.md +0 -33
  25. package/bin/database/deployment-db-manager.js +0 -527
  26. package/bin/database/enterprise-db-manager.js +0 -738
  27. package/bin/database/wrangler-d1-manager.js +0 -775
  28. package/bin/security/security-cli.js +0 -117
  29. package/bin/service-management/README.md +0 -74
  30. package/bin/service-management/create-service.js +0 -129
  31. package/bin/service-management/init-service.js +0 -103
  32. package/bin/service-management/init-service.js.backup +0 -889
  33. package/bin/shared/cloudflare/domain-discovery.js +0 -637
  34. package/bin/shared/cloudflare/domain-manager.js +0 -952
  35. package/bin/shared/cloudflare/index.js +0 -8
  36. package/bin/shared/cloudflare/ops.js +0 -401
  37. package/bin/shared/config/ConfigurationManager.js +0 -539
  38. package/bin/shared/config/cache.js +0 -1230
  39. package/bin/shared/config/command-config-manager.js +0 -184
  40. package/bin/shared/config/index.js +0 -21
  41. package/bin/shared/config/manager.js +0 -315
  42. package/bin/shared/database/connection-manager.js +0 -374
  43. package/bin/shared/database/index.js +0 -7
  44. package/bin/shared/database/orchestrator.js +0 -727
  45. package/bin/shared/deployment/auditor.js +0 -970
  46. package/bin/shared/deployment/index.js +0 -10
  47. package/bin/shared/deployment/rollback-manager.js +0 -570
  48. package/bin/shared/deployment/validator.js +0 -779
  49. package/bin/shared/index.js +0 -32
  50. package/bin/shared/logging/Logger.js +0 -214
  51. package/bin/shared/monitoring/health-checker.js +0 -484
  52. package/bin/shared/monitoring/index.js +0 -8
  53. package/bin/shared/monitoring/memory-manager.js +0 -387
  54. package/bin/shared/monitoring/production-monitor.js +0 -403
  55. package/bin/shared/production-tester/api-tester.js +0 -82
  56. package/bin/shared/production-tester/auth-tester.js +0 -132
  57. package/bin/shared/production-tester/core.js +0 -197
  58. package/bin/shared/production-tester/database-tester.js +0 -109
  59. package/bin/shared/production-tester/index.js +0 -77
  60. package/bin/shared/production-tester/load-tester.js +0 -131
  61. package/bin/shared/production-tester/performance-tester.js +0 -103
  62. package/bin/shared/security/api-token-manager.js +0 -312
  63. package/bin/shared/security/index.js +0 -8
  64. package/bin/shared/security/secret-generator.js +0 -942
  65. package/bin/shared/security/secure-token-manager.js +0 -398
  66. package/bin/shared/utils/ErrorHandler.js +0 -675
  67. package/bin/shared/utils/error-recovery.js +0 -245
  68. package/bin/shared/utils/file-manager.js +0 -162
  69. package/bin/shared/utils/formatters.js +0 -247
  70. package/bin/shared/utils/graceful-shutdown-manager.js +0 -390
  71. package/bin/shared/utils/index.js +0 -19
  72. package/bin/shared/utils/interactive-prompts.js +0 -146
  73. package/bin/shared/utils/interactive-utils.js +0 -530
  74. package/bin/shared/utils/rate-limiter.js +0 -246
  75. 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
- };