@tamyla/clodo-framework 3.1.21 → 3.1.22

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 (169) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +53 -0
  3. package/dist/bin/clodo-service.js +47 -15
  4. package/dist/bin/commands/deploy.js +115 -83
  5. package/dist/bin/commands/helpers/deployment-ui.js +138 -0
  6. package/dist/bin/commands/helpers/deployment-verification.js +251 -0
  7. package/dist/bin/commands/helpers/error-recovery.js +80 -0
  8. package/dist/bin/commands/helpers/resource-detection.js +113 -0
  9. package/dist/bin/commands/validate.js +1 -1
  10. package/dist/bin/security/security-cli.js +1 -1
  11. package/dist/bin/shared/cache/configuration-cache.js +82 -0
  12. package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
  13. package/dist/bin/shared/cloudflare/index.js +1 -1
  14. package/dist/bin/shared/cloudflare/ops.js +6 -4
  15. package/dist/bin/shared/config/ConfigurationManager.js +23 -1
  16. package/dist/bin/shared/config/command-config-manager.js +19 -3
  17. package/dist/bin/shared/config/index.js +1 -1
  18. package/dist/bin/shared/deployment/credential-collector.js +30 -7
  19. package/dist/bin/shared/deployment/index.js +2 -2
  20. package/dist/bin/shared/deployment/rollback-manager.js +4 -520
  21. package/dist/bin/shared/deployment/utilities/d1-error-recovery.js +177 -0
  22. package/dist/bin/shared/deployment/validator.js +40 -10
  23. package/dist/bin/shared/deployment/workflows/deployment-summary.js +214 -0
  24. package/dist/bin/shared/deployment/workflows/interactive-confirmation.js +188 -0
  25. package/dist/bin/shared/deployment/workflows/interactive-database-workflow.js +234 -0
  26. package/dist/bin/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
  27. package/dist/bin/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
  28. package/dist/bin/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
  29. package/dist/bin/shared/deployment/workflows/interactive-validation.js +218 -0
  30. package/dist/bin/shared/error-handling/error-classifier.js +46 -0
  31. package/dist/bin/shared/monitoring/health-checker.js +129 -1
  32. package/dist/bin/shared/monitoring/memory-manager.js +17 -6
  33. package/dist/bin/shared/routing/domain-router.js +1 -1
  34. package/dist/bin/shared/utils/deployment-validator.js +97 -0
  35. package/dist/bin/shared/utils/formatters.js +10 -0
  36. package/dist/bin/shared/utils/index.js +13 -1
  37. package/dist/bin/shared/utils/interactive-prompts.js +34 -18
  38. package/dist/bin/shared/utils/progress-manager.js +2 -2
  39. package/dist/bin/shared/utils/progress-spinner.js +53 -0
  40. package/dist/bin/shared/utils/sensitive-redactor.js +91 -0
  41. package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
  42. package/dist/security/index.js +1 -1
  43. package/dist/security/patterns/insecure-patterns.js +1 -1
  44. package/dist/utils/constants.js +102 -0
  45. package/dist/utils/deployment/wrangler-config-manager.js +215 -48
  46. package/dist/utils/framework-config.js +2 -2
  47. package/dist/utils/interactive-prompts.js +10 -59
  48. package/package.json +16 -8
  49. package/dist/bin/clodo-service-old.js +0 -868
  50. package/dist/bin/clodo-service-test.js +0 -10
  51. package/dist/bin/commands/assess.js +0 -91
  52. package/dist/bin/commands/create.js +0 -77
  53. package/dist/bin/commands/diagnose.js +0 -83
  54. package/dist/bin/commands/helpers.js +0 -138
  55. package/dist/bin/commands/update.js +0 -75
  56. package/dist/bin/database/deployment-db-manager.js +0 -423
  57. package/dist/bin/database/enterprise-db-manager.js +0 -457
  58. package/dist/bin/database/wrangler-d1-manager.js +0 -685
  59. package/dist/bin/deployment/enterprise-deploy.js +0 -877
  60. package/dist/bin/deployment/master-deploy.js +0 -1376
  61. package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
  62. package/dist/bin/deployment/modules/DeploymentConfiguration.js +0 -395
  63. package/dist/bin/deployment/modules/DeploymentOrchestrator.js +0 -492
  64. package/dist/bin/deployment/modules/EnvironmentManager.js +0 -517
  65. package/dist/bin/deployment/modules/MonitoringIntegration.js +0 -560
  66. package/dist/bin/deployment/modules/ValidationManager.js +0 -342
  67. package/dist/bin/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  68. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  69. package/dist/bin/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  70. package/dist/bin/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  71. package/dist/bin/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  72. package/dist/bin/deployment/test-interactive-utils.js +0 -66
  73. package/dist/bin/portfolio/portfolio-manager.js +0 -487
  74. package/dist/bin/service-management/create-service.js +0 -122
  75. package/dist/bin/service-management/init-service.js +0 -79
  76. package/dist/config/customers.js +0 -623
  77. package/dist/config/domains.js +0 -186
  78. package/dist/config/index.js +0 -6
  79. package/dist/database/database-orchestrator.js +0 -795
  80. package/dist/database/index.js +0 -4
  81. package/dist/deployment/index.js +0 -11
  82. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -426
  83. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  84. package/dist/deployment/orchestration/PortfolioOrchestrator.js +0 -273
  85. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +0 -231
  86. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -662
  87. package/dist/deployment/orchestration/index.js +0 -17
  88. package/dist/deployment/rollback-manager.js +0 -36
  89. package/dist/deployment/wrangler-deployer.js +0 -640
  90. package/dist/handlers/GenericRouteHandler.js +0 -532
  91. package/dist/migration/MigrationAdapters.js +0 -562
  92. package/dist/modules/ModuleManager.js +0 -668
  93. package/dist/modules/security.js +0 -96
  94. package/dist/orchestration/cross-domain-coordinator.js +0 -1083
  95. package/dist/orchestration/index.js +0 -5
  96. package/dist/orchestration/modules/DeploymentCoordinator.js +0 -368
  97. package/dist/orchestration/modules/DomainResolver.js +0 -198
  98. package/dist/orchestration/modules/StateManager.js +0 -332
  99. package/dist/orchestration/multi-domain-orchestrator.js +0 -724
  100. package/dist/routing/EnhancedRouter.js +0 -158
  101. package/dist/schema/SchemaManager.js +0 -778
  102. package/dist/service-management/ConfirmationEngine.js +0 -412
  103. package/dist/service-management/ErrorTracker.js +0 -299
  104. package/dist/service-management/GenerationEngine.js +0 -447
  105. package/dist/service-management/InputCollector.js +0 -619
  106. package/dist/service-management/ServiceCreator.js +0 -265
  107. package/dist/service-management/ServiceInitializer.js +0 -453
  108. package/dist/service-management/ServiceOrchestrator.js +0 -633
  109. package/dist/service-management/generators/BaseGenerator.js +0 -233
  110. package/dist/service-management/generators/GeneratorRegistry.js +0 -254
  111. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +0 -87
  112. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +0 -106
  113. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +0 -235
  114. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +0 -116
  115. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +0 -246
  116. package/dist/service-management/generators/code/WorkerIndexGenerator.js +0 -143
  117. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +0 -101
  118. package/dist/service-management/generators/config/DomainsConfigGenerator.js +0 -175
  119. package/dist/service-management/generators/config/EnvExampleGenerator.js +0 -178
  120. package/dist/service-management/generators/config/ProductionEnvGenerator.js +0 -97
  121. package/dist/service-management/generators/config/StagingEnvGenerator.js +0 -97
  122. package/dist/service-management/generators/config/WranglerTomlGenerator.js +0 -238
  123. package/dist/service-management/generators/core/PackageJsonGenerator.js +0 -243
  124. package/dist/service-management/generators/core/SiteConfigGenerator.js +0 -115
  125. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +0 -331
  126. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +0 -294
  127. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +0 -244
  128. package/dist/service-management/generators/documentation/ReadmeGenerator.js +0 -196
  129. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +0 -190
  130. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +0 -123
  131. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +0 -101
  132. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +0 -88
  133. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +0 -342
  134. package/dist/service-management/generators/testing/EslintConfigGenerator.js +0 -85
  135. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +0 -237
  136. package/dist/service-management/generators/testing/JestConfigGenerator.js +0 -72
  137. package/dist/service-management/generators/testing/UnitTestsGenerator.js +0 -277
  138. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +0 -71
  139. package/dist/service-management/generators/tooling/GitignoreGenerator.js +0 -143
  140. package/dist/service-management/generators/utils/FileWriter.js +0 -179
  141. package/dist/service-management/generators/utils/PathResolver.js +0 -157
  142. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +0 -111
  143. package/dist/service-management/generators/utils/TemplateEngine.js +0 -185
  144. package/dist/service-management/generators/utils/index.js +0 -18
  145. package/dist/service-management/handlers/ConfirmationHandler.js +0 -71
  146. package/dist/service-management/handlers/GenerationHandler.js +0 -80
  147. package/dist/service-management/handlers/InputHandler.js +0 -59
  148. package/dist/service-management/handlers/ValidationHandler.js +0 -203
  149. package/dist/service-management/index.js +0 -14
  150. package/dist/service-management/routing/DomainRouteMapper.js +0 -311
  151. package/dist/service-management/routing/RouteGenerator.js +0 -266
  152. package/dist/service-management/routing/WranglerRoutesBuilder.js +0 -273
  153. package/dist/service-management/routing/index.js +0 -14
  154. package/dist/service-management/services/DirectoryStructureService.js +0 -56
  155. package/dist/service-management/services/GenerationCoordinator.js +0 -208
  156. package/dist/service-management/services/GeneratorRegistry.js +0 -174
  157. package/dist/services/GenericDataService.js +0 -501
  158. package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +0 -286
  159. package/dist/ui-structures/concepts/service-lifecycle-management.md +0 -150
  160. package/dist/ui-structures/concepts/service-manifest-guide.md +0 -309
  161. package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +0 -231
  162. package/dist/ui-structures/creation/automated-generation-ui.json +0 -246
  163. package/dist/ui-structures/creation/core-inputs-ui.json +0 -217
  164. package/dist/ui-structures/creation/smart-confirmable-ui.json +0 -451
  165. package/dist/ui-structures/reference/absolutely-required-inputs.json +0 -315
  166. package/dist/ui-structures/reference/service-manifest-template.json +0 -342
  167. package/dist/version/VersionDetector.js +0 -723
  168. package/dist/worker/index.js +0 -4
  169. package/dist/worker/integration.js +0 -351
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Interactive Testing Workflow Module
3
+ *
4
+ * Provides reusable post-deployment testing workflows.
5
+ * Extracted from enterprise-deployment/master-deploy.js for modularity.
6
+ *
7
+ * @module interactive-testing-workflow
8
+ */
9
+
10
+ import { askYesNo } from '../utils/interactive-prompts.js';
11
+ import { checkHealth } from '../monitoring/health-checker.js';
12
+
13
+ /**
14
+ * Interactive Testing Workflow
15
+ * Handles post-deployment testing with user interaction
16
+ */
17
+ export class InteractiveTestingWorkflow {
18
+ /**
19
+ * @param {Object} options - Configuration options
20
+ * @param {boolean} options.interactive - Enable interactive prompts
21
+ */
22
+ constructor(options = {}) {
23
+ this.interactive = options.interactive !== false;
24
+ }
25
+
26
+ /**
27
+ * Execute post-deployment testing
28
+ *
29
+ * @param {Object} config - Deployment configuration
30
+ * @param {Object} options - Testing options
31
+ * @returns {Promise<Object>} Test results
32
+ */
33
+ async executePostDeploymentTesting(config, options = {}) {
34
+ if (!config.deployment?.runTests && !options.force) {
35
+ console.log('\n⏭️ Skipping tests (as requested)');
36
+ return {
37
+ skipped: true
38
+ };
39
+ }
40
+ console.log('\n🧪 Post-deployment Testing');
41
+ console.log('==========================');
42
+
43
+ // Ask for confirmation if interactive
44
+ if (this.interactive && !options.force) {
45
+ const runTests = await askYesNo('Run comprehensive integration tests?', 'y');
46
+ if (!runTests) {
47
+ console.log(' ⏭️ Tests skipped by user');
48
+ return {
49
+ skipped: true,
50
+ userCancelled: true
51
+ };
52
+ }
53
+ }
54
+ const results = {
55
+ health: null,
56
+ authentication: null,
57
+ overall: false
58
+ };
59
+
60
+ // Test health endpoint
61
+ results.health = await this.testHealthEndpoint(config);
62
+
63
+ // Test authentication
64
+ results.authentication = await this.testAuthentication(config);
65
+
66
+ // Determine overall success
67
+ results.overall = results.health?.success && results.authentication?.success;
68
+ console.log('\n✅ Basic tests completed');
69
+ return results;
70
+ }
71
+
72
+ /**
73
+ * Test health endpoint
74
+ *
75
+ * @param {Object} config - Configuration
76
+ * @returns {Promise<Object>} Health test result
77
+ */
78
+ async testHealthEndpoint(config) {
79
+ console.log('\n🏥 Testing health endpoint...');
80
+ try {
81
+ const health = await checkHealth(config.worker.url);
82
+ const modelCount = health.framework?.models?.length || 0;
83
+ const routeCount = health.framework?.routes?.length || 0;
84
+ console.log(` ✅ Health OK: ${modelCount} models, ${routeCount} routes`);
85
+ return {
86
+ success: true,
87
+ status: health.status,
88
+ models: modelCount,
89
+ routes: routeCount,
90
+ framework: health.framework
91
+ };
92
+ } catch (error) {
93
+ console.log(` ⚠️ Health test failed: ${error.message}`);
94
+ return {
95
+ success: false,
96
+ error: error.message
97
+ };
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Test authentication endpoint
103
+ *
104
+ * @param {Object} config - Configuration
105
+ * @returns {Promise<Object>} Authentication test result
106
+ */
107
+ async testAuthentication(config) {
108
+ console.log('\n🔐 Testing authentication...');
109
+ try {
110
+ const testEmail = `test-${Date.now()}@${config.domain}.com`;
111
+ console.log(` 📧 Testing magic link for: ${testEmail}`);
112
+ console.log(' ✅ Authentication system accessible');
113
+ return {
114
+ success: true,
115
+ testEmail,
116
+ accessible: true
117
+ };
118
+ } catch (error) {
119
+ console.log(` ⚠️ Auth test failed: ${error.message}`);
120
+ return {
121
+ success: false,
122
+ error: error.message
123
+ };
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Execute comprehensive testing with production tester
129
+ *
130
+ * @param {Object} config - Configuration
131
+ * @param {Object} productionTester - ProductionTester instance
132
+ * @returns {Promise<Object>} Comprehensive test results
133
+ */
134
+ async executeComprehensiveTesting(config, productionTester) {
135
+ console.log('\n🧪 Comprehensive Integration Testing');
136
+ console.log('====================================');
137
+ if (this.interactive) {
138
+ const runComprehensive = await askYesNo('Run comprehensive integration tests with production tester?', 'y');
139
+ if (!runComprehensive) {
140
+ console.log(' ⏭️ Comprehensive tests skipped by user');
141
+ return {
142
+ skipped: true
143
+ };
144
+ }
145
+ }
146
+ try {
147
+ const testResults = await productionTester.runComprehensiveTests({
148
+ domain: config.domain,
149
+ environment: config.environment,
150
+ workerUrl: config.worker.url,
151
+ databaseName: config.database?.name
152
+ });
153
+ if (testResults.success) {
154
+ console.log(' ✅ All comprehensive tests passed');
155
+ } else {
156
+ console.log(` ⚠️ Some tests failed: ${testResults.failedCount} failures`);
157
+ }
158
+ return testResults;
159
+ } catch (error) {
160
+ console.log(` ❌ Comprehensive testing failed: ${error.message}`);
161
+ return {
162
+ success: false,
163
+ error: error.message
164
+ };
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Execute smoke tests (quick validation)
170
+ *
171
+ * @param {Object} config - Configuration
172
+ * @returns {Promise<Object>} Smoke test results
173
+ */
174
+ async executeSmokeTests(config) {
175
+ console.log('\n🔥 Smoke Tests (Quick Validation)');
176
+ console.log('==================================');
177
+ const results = {
178
+ endpoints: [],
179
+ overall: true
180
+ };
181
+ const endpoints = [{
182
+ path: '/health',
183
+ name: 'Health Check'
184
+ }, {
185
+ path: '/auth/magic-link',
186
+ name: 'Authentication'
187
+ }, {
188
+ path: '/api',
189
+ name: 'API Root'
190
+ }];
191
+ for (const endpoint of endpoints) {
192
+ try {
193
+ const url = `${config.worker.url}${endpoint.path}`;
194
+ console.log(` Testing ${endpoint.name}...`);
195
+
196
+ // In a real implementation, we'd make HTTP requests
197
+ // For now, just check if URLs are well-formed
198
+ new URL(url);
199
+ console.log(` ✅ ${endpoint.name} endpoint valid`);
200
+ results.endpoints.push({
201
+ ...endpoint,
202
+ success: true
203
+ });
204
+ } catch (error) {
205
+ console.log(` ⚠️ ${endpoint.name} check failed: ${error.message}`);
206
+ results.endpoints.push({
207
+ ...endpoint,
208
+ success: false,
209
+ error: error.message
210
+ });
211
+ results.overall = false;
212
+ }
213
+ }
214
+ return results;
215
+ }
216
+
217
+ /**
218
+ * Get testing summary
219
+ *
220
+ * @param {Object} testResults - Test results
221
+ * @returns {string} Summary message
222
+ */
223
+ getSummary(testResults) {
224
+ if (testResults.skipped) {
225
+ return '⏭️ Tests skipped';
226
+ }
227
+ if (testResults.overall) {
228
+ return '✅ All tests passed';
229
+ }
230
+ const failures = [];
231
+ if (!testResults.health?.success) failures.push('health');
232
+ if (!testResults.authentication?.success) failures.push('authentication');
233
+ return `⚠️ Tests completed with failures: ${failures.join(', ')}`;
234
+ }
235
+ }
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Interactive Validation Workflow Module
3
+ *
4
+ * Provides reusable interactive validation workflows.
5
+ * Extracted from enterprise-deployment/master-deploy.js for modularity.
6
+ *
7
+ * @module interactive-validation
8
+ */
9
+
10
+ import { askYesNo } from '../utils/interactive-prompts.js';
11
+ import { validatePrerequisites, checkAuth, authenticate, workerExists } from '../cloudflare/ops.js';
12
+
13
+ /**
14
+ * Interactive Validation Workflow
15
+ * Handles pre-deployment checks and comprehensive validation
16
+ */
17
+ export class InteractiveValidation {
18
+ /**
19
+ * @param {Object} options - Configuration options
20
+ */
21
+ constructor(options = {}) {
22
+ this.interactive = options.interactive !== false;
23
+ }
24
+
25
+ /**
26
+ * Execute pre-deployment checks
27
+ *
28
+ * @param {Object} config - Deployment configuration
29
+ * @returns {Promise<Object>} Validation results
30
+ */
31
+ async executePreDeploymentChecks(config) {
32
+ console.log('\n✅ Pre-deployment Validation');
33
+ console.log('============================');
34
+
35
+ // Check prerequisites
36
+ await this.validatePrerequisites();
37
+
38
+ // Check authentication
39
+ await this.validateAuthentication();
40
+
41
+ // Check for existing deployments
42
+ await this.checkExistingDeployments(config);
43
+ console.log('\n✅ All pre-deployment checks passed');
44
+ return {
45
+ prerequisites: true,
46
+ authentication: true,
47
+ existingDeployments: false
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Validate system prerequisites
53
+ *
54
+ * @returns {Promise<void>}
55
+ */
56
+ async validatePrerequisites() {
57
+ console.log('\n🔍 Checking prerequisites...');
58
+ const prereqs = await validatePrerequisites();
59
+ for (const prereq of prereqs) {
60
+ if (prereq.status === 'ok') {
61
+ console.log(` ✅ ${prereq.name}: ${prereq.version}`);
62
+ } else {
63
+ throw new Error(`${prereq.name} is not available: ${prereq.error}`);
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Validate Cloudflare authentication
70
+ *
71
+ * @returns {Promise<void>}
72
+ */
73
+ async validateAuthentication() {
74
+ console.log('\n🔐 Checking Cloudflare authentication...');
75
+ const isAuthenticated = await checkAuth();
76
+ if (!isAuthenticated) {
77
+ if (!this.interactive) {
78
+ throw new Error('Cloudflare authentication required but running in non-interactive mode');
79
+ }
80
+ const shouldAuthenticate = await askYesNo('Cloudflare authentication required. Run authentication now?', 'y');
81
+ if (shouldAuthenticate) {
82
+ console.log('\n🔑 Please complete Cloudflare authentication...');
83
+ await authenticate();
84
+ } else {
85
+ throw new Error('Cloudflare authentication is required for deployment');
86
+ }
87
+ } else {
88
+ console.log(' ✅ Cloudflare: Authenticated');
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Check for existing deployments
94
+ *
95
+ * @param {Object} config - Deployment configuration
96
+ * @returns {Promise<boolean>} True if existing deployment found and should continue
97
+ */
98
+ async checkExistingDeployments(config) {
99
+ console.log('\n🔍 Checking for existing deployments...');
100
+ const workerExistsAlready = await workerExists(config.worker.name);
101
+ if (workerExistsAlready) {
102
+ console.log(` ⚠️ Worker '${config.worker.name}' already exists`);
103
+ if (!this.interactive) {
104
+ console.log(' ℹ️ Non-interactive mode: will overwrite existing worker');
105
+ return true;
106
+ }
107
+ const shouldOverwrite = await askYesNo('Do you want to overwrite the existing worker?', 'n');
108
+ if (!shouldOverwrite) {
109
+ throw new Error('Deployment cancelled - worker already exists');
110
+ }
111
+ return true;
112
+ } else {
113
+ console.log(` ✅ Worker name '${config.worker.name}' is available`);
114
+ return false;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Execute comprehensive validation
120
+ *
121
+ * @param {Object} config - Deployment configuration
122
+ * @param {Object} validationManager - ValidationManager instance
123
+ * @returns {Promise<Object>} Validation results
124
+ */
125
+ async executeComprehensiveValidation(config, validationManager) {
126
+ console.log('\n🔍 Comprehensive Validation');
127
+ console.log('==========================');
128
+ try {
129
+ const validationResult = await validationManager.validateDeploymentConfiguration({
130
+ domain: config.domain,
131
+ environment: config.environment,
132
+ worker: config.worker,
133
+ database: config.database,
134
+ secrets: config.secrets,
135
+ comprehensive: true
136
+ });
137
+ if (validationResult.valid) {
138
+ console.log(' ✅ Configuration validation passed');
139
+ if (validationResult.warnings?.length > 0) {
140
+ console.log(` ⚠️ ${validationResult.warnings.length} warnings found`);
141
+ for (const warning of validationResult.warnings) {
142
+ console.log(` - ${warning}`);
143
+ }
144
+ }
145
+ } else {
146
+ console.log(' ❌ Configuration validation failed');
147
+ for (const error of validationResult.errors) {
148
+ console.log(` - ${error}`);
149
+ }
150
+ throw new Error('Configuration validation failed');
151
+ }
152
+ return validationResult;
153
+ } catch (error) {
154
+ console.log(` ❌ Validation error: ${error.message}`);
155
+ throw error;
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Validate configuration object
161
+ *
162
+ * @param {Object} config - Configuration to validate
163
+ * @returns {Promise<Object>} Validation results
164
+ */
165
+ async validateConfiguration(config) {
166
+ const errors = [];
167
+ const warnings = [];
168
+
169
+ // Domain validation
170
+ if (!config.domain || config.domain.length === 0) {
171
+ errors.push('Domain name is required');
172
+ }
173
+
174
+ // Environment validation
175
+ if (!config.environment) {
176
+ errors.push('Environment is required');
177
+ }
178
+
179
+ // Worker validation
180
+ if (!config.worker?.name) {
181
+ errors.push('Worker name is required');
182
+ }
183
+
184
+ // Database validation
185
+ if (config.database?.name && !config.database?.id) {
186
+ warnings.push('Database name specified but no database ID');
187
+ }
188
+
189
+ // Secrets validation
190
+ if (Object.keys(config.secrets?.keys || {}).length === 0) {
191
+ warnings.push('No secrets configured');
192
+ }
193
+ return {
194
+ valid: errors.length === 0,
195
+ errors,
196
+ warnings
197
+ };
198
+ }
199
+
200
+ /**
201
+ * Get validation summary
202
+ *
203
+ * @param {Object} validationResult - Validation result
204
+ * @returns {string} Summary message
205
+ */
206
+ getValidationSummary(validationResult) {
207
+ if (validationResult.valid) {
208
+ const warningCount = validationResult.warnings?.length || 0;
209
+ if (warningCount > 0) {
210
+ return `✅ Validation passed with ${warningCount} warning(s)`;
211
+ }
212
+ return '✅ Validation passed';
213
+ } else {
214
+ const errorCount = validationResult.errors?.length || 0;
215
+ return `❌ Validation failed with ${errorCount} error(s)`;
216
+ }
217
+ }
218
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Error Classification and Recovery Module
3
+ * Provides intelligent error classification for contextual recovery suggestions
4
+ */
5
+
6
+ /**
7
+ * Classify error type for contextual recovery suggestions
8
+ * @param {Error} error - The error to classify
9
+ * @returns {string} Error type classification
10
+ */
11
+ export function classifyError(error) {
12
+ const msg = error.message.toLowerCase();
13
+ if (msg.includes('credential') || msg.includes('auth') || msg.includes('token') || msg.includes('unauthorized') || msg.includes('forbidden')) {
14
+ return 'credentials';
15
+ }
16
+ if (msg.includes('domain') || msg.includes('zone') || msg.includes('dns')) {
17
+ return 'domain';
18
+ }
19
+ if (msg.includes('network') || msg.includes('timeout') || msg.includes('econnrefused') || msg.includes('enotfound') || msg.includes('fetch failed')) {
20
+ return 'network';
21
+ }
22
+ if (msg.includes('bundle') || msg.includes('syntax') || msg.includes('compile') || msg.includes('build') || msg.includes('module not found')) {
23
+ return 'bundle';
24
+ }
25
+ if (msg.includes('database') || msg.includes('d1') || msg.includes('migration') || msg.includes('sql')) {
26
+ return 'database';
27
+ }
28
+ return 'unknown';
29
+ }
30
+
31
+ /**
32
+ * Get recovery suggestions for an error type
33
+ * @param {string} errorType - The classified error type
34
+ * @returns {Array<string>} Array of suggestion strings
35
+ */
36
+ export function getRecoverySuggestions(errorType) {
37
+ const suggestions = {
38
+ credentials: ['Check your API token, account ID, and zone ID', 'Verify token has not expired', 'Visit: https://dash.cloudflare.com/profile/api-tokens'],
39
+ domain: ['Verify domain exists in Cloudflare dashboard', 'Check API token has zone:read permissions', 'Ensure zone ID matches the domain'],
40
+ network: ['Check internet connectivity', 'Verify Cloudflare API is accessible', 'Check for firewall/proxy issues'],
41
+ bundle: ['Check for syntax errors in your code', 'Verify all dependencies are installed', 'Run: npm install or yarn install'],
42
+ database: ['Verify database exists in Cloudflare', 'Check migrations are valid SQL', 'Ensure D1 binding name matches wrangler.toml'],
43
+ unknown: ['Check the error message for details', 'Run with DEBUG=1 for full stack trace', 'Review deployment logs']
44
+ };
45
+ return suggestions[errorType] || suggestions.unknown;
46
+ }
@@ -14,7 +14,7 @@ const execAsync = promisify(exec);
14
14
  // Load framework configuration
15
15
  const {
16
16
  frameworkConfig
17
- } = await import('../../../dist/utils/framework-config.js');
17
+ } = await import('../../../utils/framework-config.js');
18
18
  const timing = frameworkConfig.getTiming();
19
19
  function makeHttpRequest(url, method = 'GET', timeout = 5000) {
20
20
  return new Promise((resolve, reject) => {
@@ -447,4 +447,132 @@ export function formatD1HealthResults(d1Results) {
447
447
  }
448
448
  }
449
449
  return lines.join('\n');
450
+ }
451
+
452
+ /**
453
+ * Modern fetch-based health check with exponential backoff
454
+ * @param {string} baseUrl - Base URL of the service
455
+ * @param {Object} options - Health check options
456
+ * @returns {Promise<Object>} Health check result
457
+ */
458
+ export async function healthCheckWithBackoff(baseUrl, options = {}) {
459
+ const {
460
+ maxAttempts = 10,
461
+ initialDelay = 1000,
462
+ maxDelay = 8000,
463
+ timeout = 5000,
464
+ silent = false
465
+ } = options;
466
+ let attempt = 0;
467
+ let delay = initialDelay;
468
+ while (attempt < maxAttempts) {
469
+ attempt++;
470
+ try {
471
+ if (!silent) {
472
+ process.stdout.write(` Attempt ${attempt}/${maxAttempts}... `);
473
+ }
474
+ const controller = new AbortController();
475
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
476
+ const startTime = Date.now();
477
+ const response = await fetch(`${baseUrl}/health`, {
478
+ signal: controller.signal,
479
+ headers: {
480
+ 'User-Agent': 'clodo-service-health-check'
481
+ }
482
+ });
483
+ clearTimeout(timeoutId);
484
+ const responseTime = Date.now() - startTime;
485
+ if (response.ok) {
486
+ // Success!
487
+ let status = null;
488
+ try {
489
+ const data = await response.json();
490
+ status = data.status || 'healthy';
491
+ } catch {
492
+ // Not JSON, that's ok
493
+ }
494
+ if (!silent) console.log('✓');
495
+ return {
496
+ healthy: true,
497
+ responseTime,
498
+ attempts: attempt,
499
+ status
500
+ };
501
+ }
502
+
503
+ // Non-200 but got response
504
+ if (!silent) console.log(`✗ (HTTP ${response.status})`);
505
+ } catch (error) {
506
+ if (!silent) {
507
+ if (error.name === 'AbortError') {
508
+ console.log('✗ (timeout)');
509
+ } else {
510
+ console.log(`✗ (${error.message})`);
511
+ }
512
+ }
513
+ }
514
+
515
+ // Wait before retry (exponential backoff)
516
+ if (attempt < maxAttempts) {
517
+ await new Promise(resolve => setTimeout(resolve, delay));
518
+ delay = Math.min(delay * 2, maxDelay); // Exponential backoff, capped
519
+ }
520
+ }
521
+ return {
522
+ healthy: false,
523
+ attempts: maxAttempts
524
+ };
525
+ }
526
+
527
+ /**
528
+ * Verify worker deployment via Cloudflare API
529
+ * @param {string} workerName - Name of the worker to verify
530
+ * @param {Object} credentials - Cloudflare credentials
531
+ * @param {Object} options - Verification options
532
+ * @returns {Promise<Object>} Verification result
533
+ */
534
+ export async function verifyWorkerDeployment(workerName, credentials, options = {}) {
535
+ const {
536
+ maxAttempts = 5,
537
+ delay = 2000,
538
+ silent = false
539
+ } = options;
540
+ let attempt = 0;
541
+ while (attempt < maxAttempts) {
542
+ attempt++;
543
+ try {
544
+ if (!silent) {
545
+ process.stdout.write(` Checking deployment status (attempt ${attempt}/${maxAttempts})... `);
546
+ }
547
+ const {
548
+ CloudflareAPI
549
+ } = await import('../../../utils/cloudflare/api.js');
550
+ const cfApi = new CloudflareAPI(credentials.token);
551
+
552
+ // List all workers to find ours
553
+ const workers = await cfApi.listWorkers(credentials.accountId);
554
+ const deployedWorker = workers.find(w => w.name === workerName);
555
+ if (deployedWorker) {
556
+ if (!silent) console.log('✓');
557
+ return {
558
+ success: true,
559
+ status: 'Active',
560
+ modifiedOn: deployedWorker.modifiedOn ? new Date(deployedWorker.modifiedOn).toLocaleString() : null,
561
+ etag: deployedWorker.etag
562
+ };
563
+ }
564
+ if (!silent) console.log('Not found yet');
565
+ } catch (error) {
566
+ if (!silent) console.log(`✗ (${error.message})`);
567
+ }
568
+
569
+ // Wait before retry
570
+ if (attempt < maxAttempts) {
571
+ await new Promise(resolve => setTimeout(resolve, delay));
572
+ }
573
+ }
574
+ return {
575
+ success: false,
576
+ error: 'Worker not found in Cloudflare API after deployment'
577
+ };
450
578
  }
@@ -46,7 +46,11 @@ export class MemoryManager {
46
46
 
47
47
  // Register process cleanup handlers
48
48
  this.registerProcessHandlers();
49
- console.log('🧠 Memory monitoring started');
49
+
50
+ // Only log if verbose mode or DEBUG is enabled
51
+ if (process.env.DEBUG || process.env.VERBOSE) {
52
+ console.log('🧠 Memory monitoring started');
53
+ }
50
54
  }
51
55
 
52
56
  /**
@@ -87,16 +91,23 @@ export class MemoryManager {
87
91
  // Check memory thresholds
88
92
  const heapUsagePercent = memUsage.heapUsed / memUsage.heapTotal;
89
93
  if (heapUsagePercent > this.config.memoryThreshold) {
90
- console.warn(`⚠️ High memory usage detected: ${(heapUsagePercent * 100).toFixed(1)}%`);
94
+ // Only warn if verbose/debug mode or if usage is critically high (>95%)
95
+ if (process.env.DEBUG || process.env.VERBOSE || heapUsagePercent > 0.95) {
96
+ console.warn(`⚠️ High memory usage detected: ${(heapUsagePercent * 100).toFixed(1)}%`);
97
+ }
91
98
 
92
99
  // Force garbage collection if available
93
- if (global.gc) {
94
- console.log('🗑️ Running forced garbage collection');
100
+ if (global.gc && heapUsagePercent > 0.90) {
101
+ if (process.env.DEBUG) {
102
+ console.log('🗑️ Running forced garbage collection');
103
+ }
95
104
  global.gc();
96
105
  }
97
106
 
98
- // Run cleanup routines
99
- this.runCleanupRoutines();
107
+ // Run cleanup routines only if critically high
108
+ if (heapUsagePercent > 0.90) {
109
+ this.runCleanupRoutines();
110
+ }
100
111
  }
101
112
 
102
113
  // Check for memory leaks
@@ -14,7 +14,7 @@
14
14
 
15
15
  import { existsSync, readFileSync } from 'fs';
16
16
  import { resolve } from 'path';
17
- import { MultiDomainOrchestrator } from "../../../orchestration/multi-domain-orchestrator.js";
17
+ import { MultiDomainOrchestrator } from '../../../orchestration/multi-domain-orchestrator.js';
18
18
  export class DomainRouter {
19
19
  constructor(options = {}) {
20
20
  this.configPath = options.configPath || './config/domains.json';