@tamyla/clodo-framework 3.1.22 → 3.1.23

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 (208) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +230 -1
  3. package/dist/cli/commands/assess.js +183 -0
  4. package/dist/cli/commands/create.js +77 -0
  5. package/dist/{bin → cli}/commands/deploy.js +8 -8
  6. package/dist/cli/commands/diagnose.js +83 -0
  7. package/dist/{bin → cli}/commands/helpers/deployment-verification.js +2 -3
  8. package/dist/{bin → cli}/commands/helpers/error-recovery.js +1 -1
  9. package/dist/{bin → cli}/commands/helpers/resource-detection.js +1 -1
  10. package/dist/cli/commands/helpers.js +110 -0
  11. package/dist/cli/commands/init-config.js +57 -0
  12. package/dist/cli/commands/update.js +75 -0
  13. package/dist/{bin → cli}/commands/validate.js +5 -5
  14. package/dist/cli/security-cli.js +118 -0
  15. package/dist/config/FeatureManager.js +6 -0
  16. package/dist/config/clodo-create.example.json +26 -0
  17. package/dist/config/clodo-deploy.example.json +41 -0
  18. package/dist/config/clodo-update.example.json +46 -0
  19. package/dist/config/clodo-validate.example.json +41 -0
  20. package/dist/config/customers/template/development.env.template +37 -0
  21. package/dist/config/customers/template/production.env.template +39 -0
  22. package/dist/config/customers/template/staging.env.template +37 -0
  23. package/dist/config/customers.js +625 -0
  24. package/dist/config/domain-examples/README.md +464 -0
  25. package/dist/config/domain-examples/environment-mapped.json +168 -0
  26. package/dist/config/domain-examples/multi-domain.json +144 -0
  27. package/dist/config/domain-examples/single-domain.json +50 -0
  28. package/dist/config/domains.js +186 -0
  29. package/dist/config/examples +12 -0
  30. package/dist/config/features.js +61 -0
  31. package/dist/config/index.js +6 -0
  32. package/dist/config/staging-deployment.json +60 -0
  33. package/dist/config/validation-config.json +347 -0
  34. package/dist/database/database-orchestrator.js +795 -0
  35. package/dist/database/index.js +4 -0
  36. package/dist/deployment/index.js +11 -0
  37. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  38. package/dist/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  39. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  40. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  41. package/dist/deployment/orchestration/index.js +17 -0
  42. package/dist/deployment/rollback-manager.js +36 -0
  43. package/dist/deployment/wrangler-deployer.js +640 -0
  44. package/dist/handlers/GenericRouteHandler.js +532 -0
  45. package/dist/lib/database/deployment-db-manager.js +423 -0
  46. package/dist/lib/database/wrangler-d1-manager.js +685 -0
  47. package/dist/lib/deployment/modules/DeploymentConfiguration.js +395 -0
  48. package/dist/lib/deployment/modules/DeploymentOrchestrator.js +492 -0
  49. package/dist/lib/deployment/modules/EnvironmentManager.js +517 -0
  50. package/dist/lib/deployment/modules/MonitoringIntegration.js +560 -0
  51. package/dist/lib/deployment/modules/ValidationManager.js +342 -0
  52. package/dist/lib/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  53. package/dist/lib/deployment/orchestration/EnterpriseOrchestrator.js +21 -0
  54. package/dist/lib/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  55. package/dist/lib/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  56. package/dist/lib/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  57. package/dist/{bin → lib}/shared/cloudflare/domain-discovery.js +1 -1
  58. package/dist/{bin → lib}/shared/cloudflare/domain-manager.js +1 -1
  59. package/dist/{bin → lib}/shared/cloudflare/ops.js +4 -4
  60. package/dist/{bin → lib}/shared/config/command-config-manager.js +1 -1
  61. package/dist/{bin → lib}/shared/config/index.js +1 -1
  62. package/dist/{bin → lib}/shared/deployment/credential-collector.js +1 -1
  63. package/dist/lib/shared/deployment/index.js +10 -0
  64. package/dist/{bin → lib}/shared/deployment/rollback-manager.js +1 -1
  65. package/dist/{bin → lib}/shared/deployment/utilities/d1-error-recovery.js +1 -1
  66. package/dist/{bin → lib}/shared/deployment/validator.js +1 -1
  67. package/dist/{bin → lib}/shared/deployment/workflows/interactive-database-workflow.js +1 -1
  68. package/dist/{bin → lib}/shared/monitoring/health-checker.js +2 -2
  69. package/dist/{bin → lib}/shared/routing/domain-router.js +1 -1
  70. package/dist/{bin → lib}/shared/validation/ValidationRegistry.js +1 -1
  71. package/dist/migration/MigrationAdapters.js +608 -0
  72. package/dist/modules/ModuleManager.js +668 -0
  73. package/dist/modules/security.js +96 -0
  74. package/dist/orchestration/cross-domain-coordinator.js +1083 -0
  75. package/dist/orchestration/index.js +5 -0
  76. package/dist/orchestration/modules/DeploymentCoordinator.js +368 -0
  77. package/dist/orchestration/modules/DomainResolver.js +198 -0
  78. package/dist/orchestration/modules/StateManager.js +332 -0
  79. package/dist/orchestration/multi-domain-orchestrator.js +765 -0
  80. package/dist/routing/EnhancedRouter.js +158 -0
  81. package/dist/schema/SchemaManager.js +778 -0
  82. package/dist/security/index.js +2 -2
  83. package/dist/service-management/ConfirmationEngine.js +412 -0
  84. package/dist/service-management/ErrorTracker.js +299 -0
  85. package/dist/service-management/GenerationEngine.js +447 -0
  86. package/dist/service-management/InputCollector.js +619 -0
  87. package/dist/service-management/ServiceCreator.js +21 -0
  88. package/dist/service-management/ServiceOrchestrator.js +631 -0
  89. package/dist/service-management/generators/BaseGenerator.js +233 -0
  90. package/dist/service-management/generators/GeneratorRegistry.js +254 -0
  91. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +87 -0
  92. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +106 -0
  93. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +235 -0
  94. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +116 -0
  95. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +246 -0
  96. package/dist/service-management/generators/code/WorkerIndexGenerator.js +143 -0
  97. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +101 -0
  98. package/dist/service-management/generators/config/DomainsConfigGenerator.js +175 -0
  99. package/dist/service-management/generators/config/EnvExampleGenerator.js +178 -0
  100. package/dist/service-management/generators/config/ProductionEnvGenerator.js +97 -0
  101. package/dist/service-management/generators/config/StagingEnvGenerator.js +97 -0
  102. package/dist/service-management/generators/config/WranglerTomlGenerator.js +238 -0
  103. package/dist/service-management/generators/core/PackageJsonGenerator.js +243 -0
  104. package/dist/service-management/generators/core/SiteConfigGenerator.js +115 -0
  105. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +331 -0
  106. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +294 -0
  107. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +244 -0
  108. package/dist/service-management/generators/documentation/ReadmeGenerator.js +196 -0
  109. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +190 -0
  110. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +123 -0
  111. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +101 -0
  112. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +88 -0
  113. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +342 -0
  114. package/dist/service-management/generators/testing/EslintConfigGenerator.js +85 -0
  115. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +237 -0
  116. package/dist/service-management/generators/testing/JestConfigGenerator.js +72 -0
  117. package/dist/service-management/generators/testing/UnitTestsGenerator.js +277 -0
  118. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +71 -0
  119. package/dist/service-management/generators/tooling/GitignoreGenerator.js +143 -0
  120. package/dist/service-management/generators/utils/FileWriter.js +179 -0
  121. package/dist/service-management/generators/utils/PathResolver.js +157 -0
  122. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +111 -0
  123. package/dist/service-management/generators/utils/TemplateEngine.js +185 -0
  124. package/dist/service-management/generators/utils/index.js +18 -0
  125. package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
  126. package/dist/service-management/handlers/GenerationHandler.js +80 -0
  127. package/dist/service-management/handlers/InputHandler.js +59 -0
  128. package/dist/service-management/handlers/ValidationHandler.js +203 -0
  129. package/dist/service-management/index.js +14 -0
  130. package/dist/service-management/routing/DomainRouteMapper.js +311 -0
  131. package/dist/service-management/routing/RouteGenerator.js +266 -0
  132. package/dist/service-management/routing/WranglerRoutesBuilder.js +273 -0
  133. package/dist/service-management/routing/index.js +14 -0
  134. package/dist/service-management/services/DirectoryStructureService.js +56 -0
  135. package/dist/service-management/services/GenerationCoordinator.js +208 -0
  136. package/dist/service-management/services/GeneratorRegistry.js +174 -0
  137. package/dist/services/GenericDataService.js +501 -0
  138. package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +286 -0
  139. package/dist/ui-structures/concepts/service-lifecycle-management.md +150 -0
  140. package/dist/ui-structures/concepts/service-manifest-guide.md +309 -0
  141. package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +231 -0
  142. package/dist/ui-structures/creation/automated-generation-ui.json +246 -0
  143. package/dist/ui-structures/creation/core-inputs-ui.json +217 -0
  144. package/dist/ui-structures/creation/smart-confirmable-ui.json +451 -0
  145. package/dist/ui-structures/reference/absolutely-required-inputs.json +315 -0
  146. package/dist/ui-structures/reference/service-manifest-template.json +342 -0
  147. package/dist/utils/cloudflare/ops.js +1 -1
  148. package/dist/utils/file-manager.js +1 -1
  149. package/dist/utils/formatters.js +1 -1
  150. package/dist/utils/logger.js +1 -1
  151. package/dist/version/VersionDetector.js +813 -0
  152. package/dist/worker/index.js +4 -0
  153. package/dist/worker/integration.js +351 -0
  154. package/package.json +7 -15
  155. package/dist/bin/security/security-cli.js +0 -108
  156. package/dist/bin/shared/deployment/index.js +0 -10
  157. /package/dist/{bin → cli}/clodo-service.js +0 -0
  158. /package/dist/{bin → cli}/commands/helpers/deployment-ui.js +0 -0
  159. /package/dist/{bin → lib}/shared/cache/configuration-cache.js +0 -0
  160. /package/dist/{bin → lib}/shared/cloudflare/index.js +0 -0
  161. /package/dist/{bin → lib}/shared/config/ConfigurationManager.js +0 -0
  162. /package/dist/{bin → lib}/shared/config/cache.js +0 -0
  163. /package/dist/{bin → lib}/shared/config/cloudflare-service-validator.js +0 -0
  164. /package/dist/{bin → lib}/shared/config/manager.js +0 -0
  165. /package/dist/{bin → lib}/shared/config/manifest-loader.js +0 -0
  166. /package/dist/{bin → lib}/shared/database/connection-manager.js +0 -0
  167. /package/dist/{bin → lib}/shared/database/index.js +0 -0
  168. /package/dist/{bin → lib}/shared/database/orchestrator.js +0 -0
  169. /package/dist/{bin → lib}/shared/deployment/auditor.js +0 -0
  170. /package/dist/{bin → lib}/shared/deployment/workflows/deployment-summary.js +0 -0
  171. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-confirmation.js +0 -0
  172. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-domain-info-gatherer.js +0 -0
  173. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-secret-workflow.js +0 -0
  174. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-testing-workflow.js +0 -0
  175. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-validation.js +0 -0
  176. /package/dist/{bin → lib}/shared/error-handling/error-classifier.js +0 -0
  177. /package/dist/{bin → lib}/shared/index.js +0 -0
  178. /package/dist/{bin → lib}/shared/logging/Logger.js +0 -0
  179. /package/dist/{bin → lib}/shared/monitoring/index.js +0 -0
  180. /package/dist/{bin → lib}/shared/monitoring/memory-manager.js +0 -0
  181. /package/dist/{bin → lib}/shared/monitoring/production-monitor.js +0 -0
  182. /package/dist/{bin → lib}/shared/production-tester/api-tester.js +0 -0
  183. /package/dist/{bin → lib}/shared/production-tester/auth-tester.js +0 -0
  184. /package/dist/{bin → lib}/shared/production-tester/core.js +0 -0
  185. /package/dist/{bin → lib}/shared/production-tester/database-tester.js +0 -0
  186. /package/dist/{bin → lib}/shared/production-tester/index.js +0 -0
  187. /package/dist/{bin → lib}/shared/production-tester/load-tester.js +0 -0
  188. /package/dist/{bin → lib}/shared/production-tester/performance-tester.js +0 -0
  189. /package/dist/{bin → lib}/shared/security/api-token-manager.js +0 -0
  190. /package/dist/{bin → lib}/shared/security/index.js +0 -0
  191. /package/dist/{bin → lib}/shared/security/secret-generator.js +0 -0
  192. /package/dist/{bin → lib}/shared/security/secure-token-manager.js +0 -0
  193. /package/dist/{bin → lib}/shared/utils/ErrorHandler.js +0 -0
  194. /package/dist/{bin → lib}/shared/utils/cli-options.js +0 -0
  195. /package/dist/{bin → lib}/shared/utils/config-loader.js +0 -0
  196. /package/dist/{bin → lib}/shared/utils/deployment-validator.js +0 -0
  197. /package/dist/{bin → lib}/shared/utils/error-recovery.js +0 -0
  198. /package/dist/{bin → lib}/shared/utils/file-manager.js +0 -0
  199. /package/dist/{bin → lib}/shared/utils/formatters.js +0 -0
  200. /package/dist/{bin → lib}/shared/utils/graceful-shutdown-manager.js +0 -0
  201. /package/dist/{bin → lib}/shared/utils/index.js +0 -0
  202. /package/dist/{bin → lib}/shared/utils/interactive-prompts.js +0 -0
  203. /package/dist/{bin → lib}/shared/utils/interactive-utils.js +0 -0
  204. /package/dist/{bin → lib}/shared/utils/output-formatter.js +0 -0
  205. /package/dist/{bin → lib}/shared/utils/progress-manager.js +0 -0
  206. /package/dist/{bin → lib}/shared/utils/progress-spinner.js +0 -0
  207. /package/dist/{bin → lib}/shared/utils/rate-limiter.js +0 -0
  208. /package/dist/{bin → lib}/shared/utils/sensitive-redactor.js +0 -0
@@ -0,0 +1,5 @@
1
+ // Orchestration Module
2
+ // Enterprise-grade deployment orchestration and coordination
3
+
4
+ export { MultiDomainOrchestrator } from './multi-domain-orchestrator.js';
5
+ export { CrossDomainCoordinator } from './cross-domain-coordinator.js';
@@ -0,0 +1,368 @@
1
+ /**
2
+ * Deployment Coordinator Module
3
+ * Handles deployment orchestration, batching, and parallel execution
4
+ * Extracted from MultiDomainOrchestrator for focused responsibility
5
+ */
6
+
7
+ export class DeploymentCoordinator {
8
+ constructor(options = {}) {
9
+ this.parallelDeployments = options.parallelDeployments || 3;
10
+ this.skipTests = options.skipTests || false;
11
+ this.dryRun = options.dryRun || false;
12
+ this.environment = options.environment || 'production';
13
+ this.batchPauseMs = options.batchPauseMs || 2000;
14
+ this.deploymentPhases = options.phases || ['validation', 'initialization', 'database', 'secrets', 'deployment', 'post-validation'];
15
+ }
16
+
17
+ /**
18
+ * Deploy to single domain with comprehensive phase management
19
+ * @param {string} domain - Domain to deploy
20
+ * @param {Object} domainState - Domain state object
21
+ * @param {Object} handlers - Handler functions for each phase
22
+ * @returns {Promise<Object>} Deployment result
23
+ */
24
+ async deploySingleDomain(domain, domainState, handlers) {
25
+ const phaseResults = {
26
+ validation: {
27
+ success: false,
28
+ errors: [],
29
+ warnings: []
30
+ },
31
+ initialization: {
32
+ success: false,
33
+ errors: [],
34
+ warnings: []
35
+ },
36
+ database: {
37
+ success: false,
38
+ errors: [],
39
+ warnings: []
40
+ },
41
+ secrets: {
42
+ success: false,
43
+ errors: [],
44
+ warnings: []
45
+ },
46
+ deployment: {
47
+ success: false,
48
+ errors: [],
49
+ warnings: []
50
+ },
51
+ 'post-validation': {
52
+ success: false,
53
+ errors: [],
54
+ warnings: []
55
+ }
56
+ };
57
+ try {
58
+ domainState.startTime = new Date();
59
+ domainState.status = 'deploying';
60
+ console.log(`\n🚀 Deploying ${domain}`);
61
+ console.log(` Deployment ID: ${domainState.deploymentId}`);
62
+ console.log(` Environment: ${this.environment}`);
63
+ let deploymentUrl = null;
64
+ let hasCriticalErrors = false;
65
+
66
+ // Execute deployment phases
67
+ for (const phase of this.deploymentPhases) {
68
+ try {
69
+ const phaseResult = await this.executeDeploymentPhase(domain, phase, domainState, handlers);
70
+ domainState.phase = `${phase}-complete`;
71
+
72
+ // Mark phase as successful
73
+ phaseResults[phase].success = true;
74
+
75
+ // Capture deployment URL from deployment phase
76
+ if (phase === 'deployment' && phaseResult) {
77
+ if (phaseResult.url) {
78
+ deploymentUrl = phaseResult.url;
79
+ }
80
+ if (phaseResult.deployed === false) {
81
+ phaseResults[phase].warnings.push('Worker deployed in dry-run mode');
82
+ }
83
+ }
84
+
85
+ // Capture database warnings
86
+ if (phase === 'database' && phaseResult) {
87
+ if (phaseResult.error) {
88
+ phaseResults[phase].warnings.push(phaseResult.error);
89
+ }
90
+ }
91
+ } catch (phaseError) {
92
+ phaseResults[phase].success = false;
93
+ phaseResults[phase].errors.push(phaseError.message);
94
+
95
+ // Determine if error is critical (stops deployment)
96
+ const criticalPhases = ['validation', 'initialization', 'deployment'];
97
+ if (criticalPhases.includes(phase)) {
98
+ console.error(` ❌ Critical error in ${phase} phase: ${phaseError.message}`);
99
+ hasCriticalErrors = true;
100
+ throw phaseError; // Stop deployment on critical errors
101
+ } else {
102
+ // Non-critical errors (database migrations, health checks) - log but continue
103
+ console.warn(` ⚠️ ${phase} phase warning: ${phaseError.message}`);
104
+ console.warn(` 💡 Deployment will continue - this can be fixed manually`);
105
+ }
106
+ }
107
+ }
108
+
109
+ // Determine overall success based on phase results
110
+ const allPhasesSuccessful = Object.values(phaseResults).every(result => result.success);
111
+ const hasWarnings = Object.values(phaseResults).some(result => result.warnings.length > 0 || result.success === false && result.errors.length === 0);
112
+ domainState.status = hasCriticalErrors ? 'failed' : allPhasesSuccessful ? 'completed' : 'completed-with-warnings';
113
+ domainState.endTime = new Date();
114
+ domainState.phaseResults = phaseResults;
115
+
116
+ // Show appropriate completion message
117
+ if (allPhasesSuccessful) {
118
+ console.log(` ✅ ${domain} deployed successfully`);
119
+ } else if (!hasCriticalErrors) {
120
+ console.log(` ⚠️ ${domain} deployed with warnings`);
121
+ this.displayPhaseWarnings(phaseResults);
122
+ }
123
+ return {
124
+ domain,
125
+ success: !hasCriticalErrors,
126
+ allPhasesSuccessful,
127
+ deploymentId: domainState.deploymentId,
128
+ duration: domainState.endTime - domainState.startTime,
129
+ phases: this.deploymentPhases.length,
130
+ url: deploymentUrl || domainState.deploymentUrl,
131
+ status: domainState.status,
132
+ phaseResults
133
+ };
134
+ } catch (error) {
135
+ domainState.status = 'failed';
136
+ domainState.error = error.message;
137
+ domainState.endTime = new Date();
138
+ domainState.phaseResults = phaseResults;
139
+ console.error(` ❌ ${domain} deployment failed: ${error.message}`);
140
+ throw error;
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Display warnings for phases that had issues
146
+ * @param {Object} phaseResults - Phase results object
147
+ */
148
+ displayPhaseWarnings(phaseResults) {
149
+ console.log(`\n 📊 Phase Status Summary:`);
150
+ for (const [phase, result] of Object.entries(phaseResults)) {
151
+ if (result.success && result.warnings.length === 0) {
152
+ console.log(` ✅ ${phase}: Success`);
153
+ } else if (result.success && result.warnings.length > 0) {
154
+ console.log(` ⚠️ ${phase}: Success with warnings`);
155
+ result.warnings.forEach(warn => console.log(` • ${warn}`));
156
+ } else {
157
+ console.log(` ❌ ${phase}: Failed`);
158
+ result.errors.forEach(err => console.log(` • ${err}`));
159
+ }
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Execute specific deployment phase
165
+ * @param {string} domain - Domain being deployed
166
+ * @param {string} phase - Phase name
167
+ * @param {Object} domainState - Domain state object
168
+ * @param {Object} handlers - Phase handler functions
169
+ * @returns {Promise<any>} Phase handler result
170
+ */
171
+ async executeDeploymentPhase(domain, phase, domainState, handlers) {
172
+ const phaseHandler = handlers[phase];
173
+ if (!phaseHandler) {
174
+ console.warn(` ⚠️ No handler for phase: ${phase}`);
175
+ return null;
176
+ }
177
+ console.log(` 📋 Phase: ${phase}`);
178
+ if (this.dryRun) {
179
+ console.log(` 🔍 DRY RUN: Would execute ${phase} for ${domain}`);
180
+ await new Promise(resolve => setTimeout(resolve, 100)); // Simulate work
181
+ return null;
182
+ }
183
+
184
+ // Skip post-validation if tests are disabled
185
+ if (phase === 'post-validation' && this.skipTests) {
186
+ console.log(` ⏭️ Skipping ${phase} (tests disabled)`);
187
+ return null;
188
+ }
189
+
190
+ // Execute handler and return result (important for capturing URLs, database IDs, etc.)
191
+ return await phaseHandler(domain, domainState);
192
+ }
193
+
194
+ /**
195
+ * Deploy to multiple domains with orchestrated coordination
196
+ * @param {Array} domains - Domains to deploy
197
+ * @param {Map} domainStates - Map of domain states
198
+ * @param {Object} handlers - Phase handler functions
199
+ * @returns {Promise<Object>} Portfolio deployment results
200
+ */
201
+ async deployPortfolio(domains, domainStates, handlers) {
202
+ const startTime = Date.now();
203
+ const results = {
204
+ successful: [],
205
+ failed: [],
206
+ totalDuration: 0,
207
+ summary: {},
208
+ batches: []
209
+ };
210
+ try {
211
+ console.log('🌐 Starting Portfolio Deployment');
212
+ console.log(`📊 Total Domains: ${domains.length}`);
213
+ console.log(`⚡ Parallel Limit: ${this.parallelDeployments}`);
214
+ console.log('');
215
+
216
+ // Deploy domains in batches based on parallel limit
217
+ const batches = this.createDeploymentBatches(domains);
218
+ for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {
219
+ const batch = batches[batchIndex];
220
+ console.log(`📦 Batch ${batchIndex + 1}/${batches.length}: ${batch.join(', ')}`);
221
+ const batchResult = await this.deployBatch(batch, domainStates, handlers);
222
+ results.batches.push(batchResult);
223
+
224
+ // Merge batch results
225
+ results.successful.push(...batchResult.successful);
226
+ results.failed.push(...batchResult.failed);
227
+
228
+ // Brief pause between batches
229
+ if (batchIndex < batches.length - 1) {
230
+ console.log(' ⏳ Pausing between batches...\n');
231
+ await new Promise(resolve => setTimeout(resolve, this.batchPauseMs));
232
+ }
233
+ }
234
+ results.totalDuration = Date.now() - startTime;
235
+ results.summary = this.generateDeploymentSummary(domains.length, results);
236
+ this.logDeploymentComplete(results);
237
+ return results;
238
+ } catch (error) {
239
+ console.error('❌ Portfolio deployment failed:', error.message);
240
+ throw error;
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Deploy a single batch of domains in parallel
246
+ * @param {Array} batch - Domains in this batch
247
+ * @param {Map} domainStates - Domain states map
248
+ * @param {Object} handlers - Phase handlers
249
+ * @returns {Promise<Object>} Batch results
250
+ */
251
+ async deployBatch(batch, domainStates, handlers) {
252
+ const batchResults = await Promise.allSettled(batch.map(domain => {
253
+ const domainState = domainStates.get(domain);
254
+ return this.deploySingleDomain(domain, domainState, handlers);
255
+ }));
256
+ const successful = [];
257
+ const failed = [];
258
+ batchResults.forEach((result, index) => {
259
+ const domain = batch[index];
260
+ if (result.status === 'fulfilled') {
261
+ successful.push({
262
+ domain,
263
+ ...result.value
264
+ });
265
+ } else {
266
+ failed.push({
267
+ domain,
268
+ error: result.reason.message
269
+ });
270
+ }
271
+ });
272
+ return {
273
+ successful,
274
+ failed,
275
+ batchSize: batch.length
276
+ };
277
+ }
278
+
279
+ /**
280
+ * Create deployment batches based on parallel limit
281
+ * @param {Array} domains - Domains to batch
282
+ * @returns {Array<Array<string>>} Batches of domains
283
+ */
284
+ createDeploymentBatches(domains) {
285
+ const batches = [];
286
+ for (let i = 0; i < domains.length; i += this.parallelDeployments) {
287
+ batches.push(domains.slice(i, i + this.parallelDeployments));
288
+ }
289
+ return batches;
290
+ }
291
+
292
+ /**
293
+ * Generate deployment summary statistics
294
+ * @param {number} totalDomains - Total domain count
295
+ * @param {Object} results - Deployment results
296
+ * @returns {Object} Summary statistics
297
+ */
298
+ generateDeploymentSummary(totalDomains, results) {
299
+ return {
300
+ total: totalDomains,
301
+ successful: results.successful.length,
302
+ failed: results.failed.length,
303
+ successRate: (results.successful.length / totalDomains * 100).toFixed(1),
304
+ averageDuration: results.successful.length > 0 ? (results.successful.reduce((sum, r) => sum + r.duration, 0) / results.successful.length / 1000).toFixed(1) : 0,
305
+ totalBatches: results.batches.length
306
+ };
307
+ }
308
+
309
+ /**
310
+ * Log deployment completion with formatted output
311
+ * @param {Object} results - Deployment results
312
+ */
313
+ logDeploymentComplete(results) {
314
+ console.log('\n🎉 PORTFOLIO DEPLOYMENT COMPLETE');
315
+ console.log('================================');
316
+ console.log(`✅ Successful: ${results.summary.successful}/${results.summary.total}`);
317
+ console.log(`❌ Failed: ${results.summary.failed}/${results.summary.total}`);
318
+ console.log(`📊 Success Rate: ${results.summary.successRate}%`);
319
+ console.log(`⏱️ Total Duration: ${(results.totalDuration / 1000).toFixed(1)}s`);
320
+ console.log(`📦 Batches Processed: ${results.summary.totalBatches}`);
321
+ if (results.summary.averageDuration > 0) {
322
+ console.log(`⏱️ Average Duration: ${results.summary.averageDuration}s per domain`);
323
+ }
324
+ if (results.failed.length > 0) {
325
+ console.log('\n❌ Failed Domains:');
326
+ results.failed.forEach(failure => {
327
+ console.log(` - ${failure.domain}: ${failure.error}`);
328
+ });
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Validate deployment coordination configuration
334
+ * @returns {Object} Validation result
335
+ */
336
+ validateConfiguration() {
337
+ const issues = [];
338
+ if (this.parallelDeployments < 1) {
339
+ issues.push('parallelDeployments must be at least 1');
340
+ }
341
+ if (this.parallelDeployments > 10) {
342
+ issues.push('parallelDeployments exceeds recommended maximum of 10');
343
+ }
344
+ if (this.batchPauseMs < 0) {
345
+ issues.push('batchPauseMs cannot be negative');
346
+ }
347
+ return {
348
+ valid: issues.length === 0,
349
+ issues,
350
+ warnings: this.parallelDeployments > 5 ? ['High parallelism may cause rate limiting'] : []
351
+ };
352
+ }
353
+
354
+ /**
355
+ * Get coordination statistics
356
+ * @returns {Object} Coordinator statistics
357
+ */
358
+ getStats() {
359
+ return {
360
+ parallelDeployments: this.parallelDeployments,
361
+ batchPauseMs: this.batchPauseMs,
362
+ phasesCount: this.deploymentPhases.length,
363
+ dryRun: this.dryRun,
364
+ skipTests: this.skipTests,
365
+ environment: this.environment
366
+ };
367
+ }
368
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Domain Resolver Module
3
+ * Handles domain discovery, validation, and configuration generation
4
+ * Extracted from MultiDomainOrchestrator for focused responsibility
5
+ */
6
+
7
+ export class DomainResolver {
8
+ constructor(options = {}) {
9
+ this.environment = options.environment || 'production';
10
+ this.validationLevel = options.validationLevel || 'basic';
11
+ this.cacheEnabled = options.cacheEnabled !== false;
12
+ this.domainCache = new Map();
13
+ }
14
+
15
+ /**
16
+ * Generate standardized domain configuration
17
+ * @param {string} domain - Domain name
18
+ * @returns {Object} Domain configuration object
19
+ */
20
+ generateDomainConfig(domain) {
21
+ if (this.cacheEnabled && this.domainCache.has(domain)) {
22
+ return this.domainCache.get(domain);
23
+ }
24
+ const cleanDomain = domain.replace(/\./g, '-').replace(/[^a-zA-Z0-9-]/g, '');
25
+ const config = {
26
+ name: domain,
27
+ cleanName: cleanDomain,
28
+ productionName: `${cleanDomain}-data-service`,
29
+ database: {
30
+ name: `${cleanDomain}-auth-db`,
31
+ id: null // Will be discovered/created
32
+ },
33
+ worker: {
34
+ name: `${cleanDomain}-data-service`
35
+ },
36
+ environments: {
37
+ production: domain,
38
+ staging: `staging.${domain}`,
39
+ development: `dev.${domain}`
40
+ },
41
+ metadata: {
42
+ generated: new Date().toISOString(),
43
+ environment: this.environment
44
+ }
45
+ };
46
+ if (this.cacheEnabled) {
47
+ this.domainCache.set(domain, config);
48
+ }
49
+ return config;
50
+ }
51
+
52
+ /**
53
+ * Validate domain prerequisites
54
+ * @param {string} domain - Domain to validate
55
+ * @returns {Promise<Object>} Validation result
56
+ */
57
+ async validateDomainPrerequisites(domain) {
58
+ console.log(` 🔍 Validating ${domain} prerequisites...`);
59
+ const validation = {
60
+ domain,
61
+ valid: true,
62
+ issues: [],
63
+ warnings: []
64
+ };
65
+ try {
66
+ // Validate Cloudflare token
67
+ if (!process.env.CLOUDFLARE_API_TOKEN) {
68
+ validation.warnings.push('CLOUDFLARE_API_TOKEN not yet configured (will be set during deployment)');
69
+ }
70
+
71
+ // Validate Cloudflare account ID
72
+ if (!process.env.CLOUDFLARE_ACCOUNT_ID) {
73
+ validation.warnings.push('CLOUDFLARE_ACCOUNT_ID not yet configured (will be set during deployment)');
74
+ }
75
+
76
+ // Validate domain format
77
+ if (!this.isValidDomainFormat(domain)) {
78
+ validation.valid = false;
79
+ validation.issues.push(`Invalid domain format: ${domain}`);
80
+ }
81
+
82
+ // Additional validation based on level
83
+ if (this.validationLevel === 'comprehensive') {
84
+ await this.performComprehensiveValidation(domain, validation);
85
+ }
86
+ } catch (error) {
87
+ validation.valid = false;
88
+ validation.issues.push(`Validation error: ${error.message}`);
89
+ }
90
+ return validation;
91
+ }
92
+
93
+ /**
94
+ * Resolve multiple domains with their configurations
95
+ * @param {Array} domains - Array of domain names
96
+ * @returns {Promise<Array>} Array of resolved domain configurations
97
+ */
98
+ async resolveMultipleDomains(domains) {
99
+ const resolved = [];
100
+ for (const domain of domains) {
101
+ const config = this.generateDomainConfig(domain);
102
+ const validation = await this.validateDomainPrerequisites(domain);
103
+ resolved.push({
104
+ ...config,
105
+ validation,
106
+ isValid: validation.valid
107
+ });
108
+ }
109
+ return resolved;
110
+ }
111
+
112
+ /**
113
+ * Discover domains from configuration files or runtime
114
+ * @param {Object} options - Discovery options
115
+ * @returns {Promise<Array>} Discovered domains
116
+ */
117
+ async discoverDomains(options = {}) {
118
+ const discovered = [];
119
+ if (options.sources?.includes('config')) {
120
+ const configDomains = await this.discoverFromConfig();
121
+ discovered.push(...configDomains);
122
+ }
123
+ if (options.sources?.includes('runtime')) {
124
+ const runtimeDomains = await this.discoverFromRuntime();
125
+ discovered.push(...runtimeDomains);
126
+ }
127
+
128
+ // Remove duplicates and validate
129
+ const uniqueDomains = [...new Set(discovered)];
130
+ return await this.resolveMultipleDomains(uniqueDomains);
131
+ }
132
+
133
+ /**
134
+ * Check if domain format is valid
135
+ * @param {string} domain - Domain to check
136
+ * @returns {boolean} Valid status
137
+ */
138
+ isValidDomainFormat(domain) {
139
+ const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.[a-zA-Z]{2,}$/;
140
+ return domainRegex.test(domain);
141
+ }
142
+
143
+ /**
144
+ * Perform comprehensive domain validation
145
+ * @param {string} domain - Domain to validate
146
+ * @param {Object} validation - Validation object to update
147
+ */
148
+ async performComprehensiveValidation(domain, validation) {
149
+ // Check domain accessibility (basic DNS check)
150
+ try {
151
+ // Note: In a real implementation, this would do DNS lookups
152
+ // For now, just simulate validation
153
+ if (domain.includes('localhost') || domain.includes('127.0.0.1')) {
154
+ validation.warnings.push('Using local domain - may not be accessible externally');
155
+ }
156
+ } catch (error) {
157
+ validation.warnings.push(`DNS validation failed: ${error.message}`);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Discover domains from configuration files
163
+ * @returns {Promise<Array>} Configuration-based domains
164
+ */
165
+ async discoverFromConfig() {
166
+ // Placeholder - would read from actual config files
167
+ console.log(' 📂 Discovering domains from configuration...');
168
+ return [];
169
+ }
170
+
171
+ /**
172
+ * Discover domains from runtime (e.g., Cloudflare API)
173
+ * @returns {Promise<Array>} Runtime-discovered domains
174
+ */
175
+ async discoverFromRuntime() {
176
+ // Placeholder - would query Cloudflare API or other runtime sources
177
+ console.log(' 🌐 Discovering domains from runtime...');
178
+ return [];
179
+ }
180
+
181
+ /**
182
+ * Clear domain configuration cache
183
+ */
184
+ clearCache() {
185
+ this.domainCache.clear();
186
+ }
187
+
188
+ /**
189
+ * Get cache statistics
190
+ * @returns {Object} Cache statistics
191
+ */
192
+ getCacheStats() {
193
+ return {
194
+ size: this.domainCache.size,
195
+ enabled: this.cacheEnabled
196
+ };
197
+ }
198
+ }