@tamyla/clodo-framework 3.1.21 → 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 (150) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +283 -1
  3. package/dist/{bin → cli}/clodo-service.js +47 -15
  4. package/dist/cli/commands/assess.js +183 -0
  5. package/dist/{bin → cli}/commands/create.js +5 -5
  6. package/dist/{bin → cli}/commands/deploy.js +122 -90
  7. package/dist/{bin → cli}/commands/diagnose.js +5 -5
  8. package/dist/cli/commands/helpers/deployment-ui.js +138 -0
  9. package/dist/cli/commands/helpers/deployment-verification.js +250 -0
  10. package/dist/cli/commands/helpers/error-recovery.js +80 -0
  11. package/dist/cli/commands/helpers/resource-detection.js +113 -0
  12. package/dist/{bin → cli}/commands/helpers.js +0 -28
  13. package/dist/cli/commands/init-config.js +57 -0
  14. package/dist/{bin → cli}/commands/update.js +5 -5
  15. package/dist/{bin → cli}/commands/validate.js +5 -5
  16. package/dist/cli/security-cli.js +118 -0
  17. package/dist/config/FeatureManager.js +6 -0
  18. package/dist/config/clodo-create.example.json +26 -0
  19. package/dist/config/clodo-deploy.example.json +41 -0
  20. package/dist/config/clodo-update.example.json +46 -0
  21. package/dist/config/clodo-validate.example.json +41 -0
  22. package/dist/config/customers/template/development.env.template +37 -0
  23. package/dist/config/customers/template/production.env.template +39 -0
  24. package/dist/config/customers/template/staging.env.template +37 -0
  25. package/dist/config/customers.js +28 -26
  26. package/dist/config/domain-examples/README.md +464 -0
  27. package/dist/config/domain-examples/environment-mapped.json +168 -0
  28. package/dist/config/domain-examples/multi-domain.json +144 -0
  29. package/dist/config/domain-examples/single-domain.json +50 -0
  30. package/dist/config/examples +12 -0
  31. package/dist/config/features.js +61 -0
  32. package/dist/config/staging-deployment.json +60 -0
  33. package/dist/config/validation-config.json +347 -0
  34. package/dist/deployment/wrangler-deployer.js +1 -1
  35. package/dist/{bin → lib}/deployment/modules/DeploymentOrchestrator.js +2 -2
  36. package/dist/{bin → lib}/deployment/modules/EnvironmentManager.js +2 -2
  37. package/dist/lib/deployment/orchestration/EnterpriseOrchestrator.js +21 -0
  38. package/dist/lib/shared/cache/configuration-cache.js +82 -0
  39. package/dist/{bin → lib}/shared/cloudflare/domain-discovery.js +1 -1
  40. package/dist/{bin → lib}/shared/cloudflare/domain-manager.js +1 -1
  41. package/dist/{bin → lib}/shared/cloudflare/index.js +1 -1
  42. package/dist/{bin → lib}/shared/cloudflare/ops.js +10 -8
  43. package/dist/{bin → lib}/shared/config/ConfigurationManager.js +23 -1
  44. package/dist/{bin → lib}/shared/config/command-config-manager.js +19 -3
  45. package/dist/{bin → lib}/shared/config/index.js +1 -1
  46. package/dist/{bin → lib}/shared/deployment/credential-collector.js +30 -7
  47. package/dist/lib/shared/deployment/index.js +10 -0
  48. package/dist/lib/shared/deployment/rollback-manager.js +7 -0
  49. package/dist/lib/shared/deployment/utilities/d1-error-recovery.js +177 -0
  50. package/dist/{bin → lib}/shared/deployment/validator.js +40 -10
  51. package/dist/lib/shared/deployment/workflows/deployment-summary.js +214 -0
  52. package/dist/lib/shared/deployment/workflows/interactive-confirmation.js +188 -0
  53. package/dist/lib/shared/deployment/workflows/interactive-database-workflow.js +234 -0
  54. package/dist/lib/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
  55. package/dist/lib/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
  56. package/dist/lib/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
  57. package/dist/lib/shared/deployment/workflows/interactive-validation.js +218 -0
  58. package/dist/lib/shared/error-handling/error-classifier.js +46 -0
  59. package/dist/{bin → lib}/shared/monitoring/health-checker.js +129 -1
  60. package/dist/{bin → lib}/shared/monitoring/memory-manager.js +17 -6
  61. package/dist/{bin → lib}/shared/routing/domain-router.js +1 -1
  62. package/dist/lib/shared/utils/deployment-validator.js +97 -0
  63. package/dist/{bin → lib}/shared/utils/formatters.js +10 -0
  64. package/dist/{bin → lib}/shared/utils/index.js +13 -1
  65. package/dist/{bin → lib}/shared/utils/interactive-prompts.js +34 -18
  66. package/dist/{bin → lib}/shared/utils/progress-manager.js +2 -2
  67. package/dist/lib/shared/utils/progress-spinner.js +53 -0
  68. package/dist/lib/shared/utils/sensitive-redactor.js +91 -0
  69. package/dist/{bin → lib}/shared/validation/ValidationRegistry.js +1 -1
  70. package/dist/migration/MigrationAdapters.js +50 -4
  71. package/dist/orchestration/cross-domain-coordinator.js +5 -5
  72. package/dist/orchestration/multi-domain-orchestrator.js +63 -22
  73. package/dist/security/index.js +2 -2
  74. package/dist/security/patterns/insecure-patterns.js +1 -1
  75. package/dist/service-management/ConfirmationEngine.js +1 -1
  76. package/dist/service-management/ErrorTracker.js +1 -1
  77. package/dist/service-management/InputCollector.js +1 -1
  78. package/dist/service-management/ServiceCreator.js +11 -255
  79. package/dist/service-management/ServiceOrchestrator.js +0 -2
  80. package/dist/service-management/generators/testing/UnitTestsGenerator.js +4 -4
  81. package/dist/service-management/index.js +1 -1
  82. package/dist/utils/cloudflare/ops.js +1 -1
  83. package/dist/utils/constants.js +102 -0
  84. package/dist/utils/deployment/wrangler-config-manager.js +215 -48
  85. package/dist/utils/file-manager.js +1 -1
  86. package/dist/utils/formatters.js +1 -1
  87. package/dist/utils/framework-config.js +2 -2
  88. package/dist/utils/interactive-prompts.js +10 -59
  89. package/dist/utils/logger.js +1 -1
  90. package/dist/version/VersionDetector.js +99 -9
  91. package/dist/worker/integration.js +1 -1
  92. package/package.json +10 -10
  93. package/dist/bin/clodo-service-old.js +0 -868
  94. package/dist/bin/clodo-service-test.js +0 -10
  95. package/dist/bin/commands/assess.js +0 -91
  96. package/dist/bin/database/enterprise-db-manager.js +0 -457
  97. package/dist/bin/deployment/enterprise-deploy.js +0 -877
  98. package/dist/bin/deployment/master-deploy.js +0 -1376
  99. package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
  100. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  101. package/dist/bin/deployment/test-interactive-utils.js +0 -66
  102. package/dist/bin/portfolio/portfolio-manager.js +0 -487
  103. package/dist/bin/security/security-cli.js +0 -108
  104. package/dist/bin/service-management/create-service.js +0 -122
  105. package/dist/bin/service-management/init-service.js +0 -79
  106. package/dist/bin/shared/deployment/index.js +0 -10
  107. package/dist/bin/shared/deployment/rollback-manager.js +0 -523
  108. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  109. package/dist/service-management/ServiceInitializer.js +0 -453
  110. /package/dist/{bin → lib}/database/deployment-db-manager.js +0 -0
  111. /package/dist/{bin → lib}/database/wrangler-d1-manager.js +0 -0
  112. /package/dist/{bin → lib}/deployment/modules/DeploymentConfiguration.js +0 -0
  113. /package/dist/{bin → lib}/deployment/modules/MonitoringIntegration.js +0 -0
  114. /package/dist/{bin → lib}/deployment/modules/ValidationManager.js +0 -0
  115. /package/dist/{bin → lib}/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -0
  116. /package/dist/{bin → lib}/deployment/orchestration/PortfolioOrchestrator.js +0 -0
  117. /package/dist/{bin → lib}/deployment/orchestration/SingleServiceOrchestrator.js +0 -0
  118. /package/dist/{bin → lib}/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -0
  119. /package/dist/{bin → lib}/shared/config/cache.js +0 -0
  120. /package/dist/{bin → lib}/shared/config/cloudflare-service-validator.js +0 -0
  121. /package/dist/{bin → lib}/shared/config/manager.js +0 -0
  122. /package/dist/{bin → lib}/shared/config/manifest-loader.js +0 -0
  123. /package/dist/{bin → lib}/shared/database/connection-manager.js +0 -0
  124. /package/dist/{bin → lib}/shared/database/index.js +0 -0
  125. /package/dist/{bin → lib}/shared/database/orchestrator.js +0 -0
  126. /package/dist/{bin → lib}/shared/deployment/auditor.js +0 -0
  127. /package/dist/{bin → lib}/shared/index.js +0 -0
  128. /package/dist/{bin → lib}/shared/logging/Logger.js +0 -0
  129. /package/dist/{bin → lib}/shared/monitoring/index.js +0 -0
  130. /package/dist/{bin → lib}/shared/monitoring/production-monitor.js +0 -0
  131. /package/dist/{bin → lib}/shared/production-tester/api-tester.js +0 -0
  132. /package/dist/{bin → lib}/shared/production-tester/auth-tester.js +0 -0
  133. /package/dist/{bin → lib}/shared/production-tester/core.js +0 -0
  134. /package/dist/{bin → lib}/shared/production-tester/database-tester.js +0 -0
  135. /package/dist/{bin → lib}/shared/production-tester/index.js +0 -0
  136. /package/dist/{bin → lib}/shared/production-tester/load-tester.js +0 -0
  137. /package/dist/{bin → lib}/shared/production-tester/performance-tester.js +0 -0
  138. /package/dist/{bin → lib}/shared/security/api-token-manager.js +0 -0
  139. /package/dist/{bin → lib}/shared/security/index.js +0 -0
  140. /package/dist/{bin → lib}/shared/security/secret-generator.js +0 -0
  141. /package/dist/{bin → lib}/shared/security/secure-token-manager.js +0 -0
  142. /package/dist/{bin → lib}/shared/utils/ErrorHandler.js +0 -0
  143. /package/dist/{bin → lib}/shared/utils/cli-options.js +0 -0
  144. /package/dist/{bin → lib}/shared/utils/config-loader.js +0 -0
  145. /package/dist/{bin → lib}/shared/utils/error-recovery.js +0 -0
  146. /package/dist/{bin → lib}/shared/utils/file-manager.js +0 -0
  147. /package/dist/{bin → lib}/shared/utils/graceful-shutdown-manager.js +0 -0
  148. /package/dist/{bin → lib}/shared/utils/interactive-utils.js +0 -0
  149. /package/dist/{bin → lib}/shared/utils/output-formatter.js +0 -0
  150. /package/dist/{bin → lib}/shared/utils/rate-limiter.js +0 -0
@@ -1,877 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Enterprise Deployment CLI
5
- *
6
- * Advanced command-line deployment system powered by enterprise modules.
7
- * Provides comprehensive deployment options, portfolio management, and automation.
8
- *
9
- * Enterprise Features:
10
- * - Command-line driven deployment with rich options
11
- * - Multi-domain and portfolio deployment capabilities
12
- * - Automated configuration discovery and generation
13
- * - Advanced validation and testing pipelines
14
- * - Rollback and recovery management
15
- * - Comprehensive audit and reporting
16
- * - CI/CD integration support
17
- * - Batch operations and automation
18
- * - Performance monitoring and analytics
19
- * - Compliance and security features
20
- *
21
- * @version 2.0.0 - Enterprise Edition
22
- */
23
- import { program } from 'commander';
24
- import { existsSync, readFileSync } from 'fs';
25
- import { join } from 'path';
26
-
27
- // Enterprise module imports - organized shared modules
28
- import { MultiDomainOrchestrator } from "../../orchestration/multi-domain-orchestrator.js";
29
- import { RollbackManager } from '../shared/deployment/rollback-manager.js';
30
- import { ProductionTester } from '../shared/production-tester/index.js';
31
- import { DeploymentValidator } from '../shared/deployment/validator.js';
32
- import { DomainDiscovery } from '../shared/cloudflare/domain-discovery.js';
33
- import { DatabaseOrchestrator } from "../../database/database-orchestrator.js";
34
- import { EnhancedSecretManager } from '../shared/security/secret-generator.js';
35
- import { DeploymentAuditor } from '../shared/deployment/auditor.js';
36
- import { ConfigurationCacheManager } from '../shared/config/cache.js';
37
- import { CrossDomainCoordinator } from "../../orchestration/cross-domain-coordinator.js";
38
- import { askChoice, askUser, closePrompts } from '../shared/utils/interactive-prompts.js';
39
- import { CloudflareDomainManager } from '../shared/cloudflare/domain-manager.js';
40
-
41
- // Consolidated environment manager
42
- import { EnvironmentManager } from './modules/EnvironmentManager.js';
43
- class EnterpriseDeploymentCLI {
44
- constructor() {
45
- this.version = '2.0.0';
46
- this.modules = {};
47
- this.globalConfig = this.loadGlobalConfig();
48
- }
49
-
50
- /**
51
- * Initialize the CLI asynchronously
52
- */
53
- async initialize() {
54
- await this.initializeModules();
55
- this.setupCommands();
56
- }
57
-
58
- /**
59
- * Ensure modules are initialized (lazy initialization)
60
- */
61
- async ensureInitialized() {
62
- if (!this.modules || Object.keys(this.modules).length === 0) {
63
- await this.initializeModules();
64
- }
65
- }
66
-
67
- /**
68
- * Load global configuration
69
- */
70
- loadGlobalConfig() {
71
- const configPath = join(process.cwd(), 'enterprise-deploy.config.json');
72
- if (existsSync(configPath)) {
73
- try {
74
- return JSON.parse(readFileSync(configPath, 'utf8'));
75
- } catch (error) {
76
- console.warn('⚠️ Failed to load config file, using defaults');
77
- }
78
- }
79
- return {
80
- defaultEnvironment: 'production',
81
- validationLevel: 'comprehensive',
82
- auditLevel: 'detailed',
83
- enableRollback: true,
84
- enableTesting: true,
85
- maxConcurrentDeployments: 3,
86
- deploymentTimeout: 1800000,
87
- // 30 minutes
88
- outputFormat: 'enhanced' // 'minimal', 'standard', 'enhanced'
89
- };
90
- }
91
-
92
- /**
93
- * Add unified environment option to command
94
- * Consolidates -e, --env option definition across all commands
95
- */
96
- addEnvironmentOption(command, defaultValue) {
97
- const envOpt = EnvironmentManager.getEnvironmentOption();
98
- return command.option(envOpt.flag, envOpt.description, defaultValue || this.globalConfig.defaultEnvironment);
99
- }
100
-
101
- /**
102
- * Initialize enterprise modules
103
- */
104
- async initializeModules() {
105
- const domainDiscovery = new DomainDiscovery({
106
- enableCaching: true
107
- });
108
- domainDiscovery.initializeDiscovery();
109
- this.modules = {
110
- orchestrator: new MultiDomainOrchestrator({
111
- maxConcurrentDeployments: this.globalConfig.maxConcurrentDeployments,
112
- timeout: this.globalConfig.deploymentTimeout
113
- }),
114
- validator: new DeploymentValidator({
115
- validationLevel: this.globalConfig.validationLevel
116
- }),
117
- rollbackManager: new RollbackManager({
118
- autoRollbackEnabled: this.globalConfig.enableRollback
119
- }),
120
- domainDiscovery,
121
- databaseOrchestrator: new DatabaseOrchestrator({
122
- enableSafeMode: true
123
- }),
124
- secretManager: new EnhancedSecretManager({
125
- crossDomainCoordination: true
126
- }),
127
- productionTester: new ProductionTester({
128
- comprehensiveTests: this.globalConfig.enableTesting
129
- }),
130
- auditor: new DeploymentAuditor({
131
- auditLevel: this.globalConfig.auditLevel
132
- }),
133
- configCache: new ConfigurationCacheManager({
134
- enableRuntimeDiscovery: true
135
- }),
136
- coordinator: new CrossDomainCoordinator({
137
- portfolioName: 'enterprise-cli-portfolio'
138
- })
139
- };
140
-
141
- // Initialize async components
142
- await this.modules.orchestrator.initialize();
143
- await this.modules.rollbackManager.initialize();
144
- await this.modules.configCache.initialize();
145
- }
146
-
147
- /**
148
- * Setup CLI commands
149
- */
150
- setupCommands() {
151
- program.name('enterprise-deploy').description('Enterprise Deployment System - Advanced deployment and portfolio management').version(this.version);
152
-
153
- // Single domain deployment
154
- this.addEnvironmentOption(program.command('deploy [domain]').description('Deploy a single domain with enterprise features')).option('-v, --validation <level>', 'validation level (basic|standard|comprehensive)', this.globalConfig.validationLevel).option('-a, --audit <level>', 'audit level (minimal|standard|detailed|verbose)', this.globalConfig.auditLevel).option('-i, --interactive', 'interactive mode - select domain from available options').option('--no-tests', 'skip production testing').option('--no-rollback', 'disable automatic rollback').option('--dry-run', 'simulate deployment without changes').option('--force', 'force deployment even if validation fails').option('--config <file>', 'custom configuration file').action(async (domain, options) => {
155
- try {
156
- await this.ensureInitialized();
157
- if (options.interactive && !domain) {
158
- domain = await this.selectDomainInteractively();
159
- }
160
- if (!domain) {
161
- console.error('❌ Domain is required. Use --interactive to select from available domains, or provide domain as argument.');
162
- process.exit(1);
163
- }
164
- await this.deploySingleDomain(domain, options);
165
- process.exit(0);
166
- } catch (error) {
167
- console.error('❌ Deployment failed:', error.message);
168
- process.exit(1);
169
- }
170
- });
171
-
172
- // Multi-domain deployment
173
- this.addEnvironmentOption(program.command('deploy-multi <domains...>').description('Deploy multiple domains with coordination')).option('-b, --batch-size <size>', 'batch size for parallel deployments', '3').option('--coordination', 'enable cross-domain coordination').option('--shared-secrets', 'enable shared secret management').option('--dependency-order', 'resolve and use dependency ordering').option('--dry-run', 'simulate deployment without changes').action(async (domains, options) => {
174
- try {
175
- await this.deployMultiDomain(domains, options);
176
- process.exit(0);
177
- } catch (error) {
178
- console.error('❌ Multi-domain deployment failed:', error.message);
179
- process.exit(1);
180
- }
181
- });
182
-
183
- // Portfolio deployment
184
- this.addEnvironmentOption(program.command('deploy-portfolio').description('Deploy entire domain portfolio')).option('-f, --filter <pattern>', 'filter domains by pattern').option('--exclude <pattern>', 'exclude domains matching pattern').option('--health-check', 'run health checks before deployment').option('--rollback-threshold <percent>', 'rollback threshold (0-1)', '0.8').option('--dry-run', 'simulate deployment without changes').action(async options => {
185
- try {
186
- await this.deployPortfolio(options);
187
- process.exit(0);
188
- } catch (error) {
189
- console.error('❌ Portfolio deployment failed:', error.message);
190
- process.exit(1);
191
- }
192
- });
193
-
194
- // Discovery commands
195
- program.command('discover <domain>').description('Discover domain configuration from Cloudflare').option('--token <token>', 'Cloudflare API token').option('--cache', 'cache discovered configuration').option('--update-config', 'update domains.js with discovery results').action(async (domain, options) => {
196
- try {
197
- await this.discoverDomain(domain, options);
198
- process.exit(0);
199
- } catch (error) {
200
- console.error('❌ Domain discovery failed:', error.message);
201
- process.exit(1);
202
- }
203
- });
204
- program.command('discover-portfolio').description('Discover entire portfolio configuration').option('--token <token>', 'Cloudflare API token').option('--update-all', 'update all domain configurations').action(options => this.discoverPortfolio(options));
205
-
206
- // Validation commands
207
- this.addEnvironmentOption(program.command('validate <domain>').description('Validate domain deployment readiness')).option('-l, --level <level>', 'validation level', this.globalConfig.validationLevel).option('--fix', 'attempt to fix validation issues').action((domain, options) => this.validateDomain(domain, options));
208
- this.addEnvironmentOption(program.command('validate-portfolio').description('Validate entire portfolio deployment readiness')).option('--cross-domain', 'include cross-domain compatibility checks').option('--report <format>', 'generate validation report (json|html|csv)', 'json').action(options => this.validatePortfolio(options));
209
-
210
- // Testing commands
211
- program.command('test <domain>').description('Run production tests for domain').option('--url <url>', 'custom URL to test').option('--suites <suites>', 'test suites to run (comma-separated)', 'health,endpoints,integration').option('--timeout <ms>', 'test timeout in milliseconds', '30000').option('--report <format>', 'test report format (json|html|junit)', 'json').action((domain, options) => this.testDomain(domain, options));
212
- program.command('test-portfolio').description('Run production tests for entire portfolio').option('--parallel', 'run tests in parallel').option('--threshold <percent>', 'success threshold (0-1)', '0.9').option('--report <format>', 'test report format', 'html').action(options => this.testPortfolio(options));
213
-
214
- // Database commands
215
- this.addEnvironmentOption(program.command('db-migrate <domain>').description('Run database migrations for domain')).option('--create-db', 'create database if it doesn\'t exist').option('--dry-run', 'show migrations without executing').action((domain, options) => this.migrateDomain(domain, options));
216
- this.addEnvironmentOption(program.command('db-migrate-all').description('Run database migrations for all domains')).option('--parallel', 'run migrations in parallel').option('--safe-mode', 'enable extra safety checks').action(options => this.migrateAll(options));
217
-
218
- // Secret management commands
219
- this.addEnvironmentOption(program.command('secrets-generate <domain>').description('Generate secrets for domain')).option('--formats <formats>', 'output formats (comma-separated)', 'env,json,wrangler').option('--coordinate', 'coordinate with other domains').option('--deploy', 'deploy secrets to Cloudflare').action((domain, options) => this.generateSecrets(domain, options));
220
- this.addEnvironmentOption(program.command('secrets-coordinate <domains...>').description('Coordinate secrets across multiple domains')).option('--sync-critical', 'sync critical secrets across domains').option('--deploy', 'deploy coordinated secrets').action((domains, options) => this.coordinateSecrets(domains, options));
221
-
222
- // Rollback commands
223
- program.command('rollback <domain>').description('Rollback domain deployment').option('--deployment-id <id>', 'specific deployment ID to rollback').option('--reason <reason>', 'rollback reason for audit').option('--force', 'force rollback without confirmation').action((domain, options) => this.rollbackDomain(domain, options));
224
- program.command('rollback-portfolio').description('Rollback portfolio deployment').option('--coordination-id <id>', 'coordination ID to rollback').option('--partial', 'allow partial rollback').action(options => this.rollbackPortfolio(options));
225
-
226
- // Monitoring commands
227
- program.command('monitor').description('Monitor portfolio health').option('--interval <ms>', 'monitoring interval', '300000').option('--alert-webhook <url>', 'webhook for alerts').option('--continuous', 'run continuous monitoring').action(options => this.monitorPortfolio(options));
228
- program.command('status [domain]').description('Get deployment status').option('--detailed', 'show detailed status').option('--format <format>', 'output format (table|json|yaml)', 'table').action((domain, options) => this.getStatus(domain, options));
229
-
230
- // Audit commands
231
- program.command('audit <domain>').description('Generate audit report for domain').option('--deployment-id <id>', 'specific deployment ID').option('--format <format>', 'report format (json|html|csv)', 'html').option('--period <days>', 'audit period in days', '30').action((domain, options) => this.auditDomain(domain, options));
232
- program.command('audit-portfolio').description('Generate portfolio audit report').option('--format <format>', 'report format', 'html').option('--compliance', 'include compliance report').action(options => this.auditPortfolio(options));
233
-
234
- // Configuration commands
235
- program.command('config-cache <domain>').description('Manage configuration cache for domain').option('--clear', 'clear cached configuration').option('--refresh', 'refresh cached configuration').option('--show', 'show cached configuration').action((domain, options) => this.manageConfigCache(domain, options));
236
-
237
- // Utility commands
238
- program.command('list-domains').description('List all discovered domains').option('--format <format>', 'output format (table|json|yaml)', 'table').action(async options => {
239
- try {
240
- await this.ensureInitialized();
241
- await this.listDomains(options);
242
- process.exit(0);
243
- } catch (error) {
244
- console.error('❌ List domains failed:', error.message);
245
- process.exit(1);
246
- }
247
- });
248
- program.command('cleanup').description('Clean up old deployments and logs').option('--days <days>', 'retention period in days', '90').option('--force', 'force cleanup without confirmation').action(options => this.cleanupDeployments(options));
249
-
250
- // Global options
251
- program.option('--verbose', 'verbose output').option('--quiet', 'quiet mode - minimal output').option('--no-color', 'disable colored output').option('--output <format>', 'global output format override');
252
- }
253
-
254
- /**
255
- * Deploy single domain
256
- */
257
- async deploySingleDomain(domain, options) {
258
- try {
259
- this.logOutput(`🚀 Enterprise deployment: ${domain}`, 'info');
260
-
261
- // Step 1: Comprehensive Cloudflare Domain Verification
262
- const domainManager = new CloudflareDomainManager();
263
- let domainVerification;
264
- try {
265
- this.logOutput('🔍 Verifying domain with Cloudflare...', 'info');
266
- domainVerification = await domainManager.verifyDomainWorkflow(domain);
267
- if (domainVerification.action === 'choose_different') {
268
- // User wants to choose different domain
269
- domain = await this.selectDomainInteractively();
270
- this.logOutput(`🚀 Enterprise deployment: ${domain}`, 'info');
271
- // Re-verify the new domain
272
- domainVerification = await domainManager.verifyDomainWorkflow(domain);
273
- }
274
-
275
- // Log domain verification results
276
- this.logOutput(`✅ Domain verification complete:`, 'success');
277
- this.logOutput(` 📊 Status: ${domainVerification.domainStatus}`, 'info');
278
- this.logOutput(` 🎯 Action: ${domainVerification.recommendedAction}`, 'info');
279
- if (domainVerification.existingServices?.length > 0) {
280
- this.logOutput(` 📋 Existing services: ${domainVerification.existingServices.length}`, 'info');
281
- }
282
- } catch (error) {
283
- if (error.message.includes('DEPLOYMENT_CANCELLED') || error.message.includes('authentication required')) {
284
- this.logOutput(`❌ ${error.message}`, 'error');
285
- return;
286
- }
287
- // Continue with deployment even if verification fails
288
- this.logOutput(`⚠️ Domain verification failed: ${error.message}`, 'warn');
289
- this.logOutput('🔄 Continuing with deployment...', 'info');
290
- domainVerification = {
291
- domainStatus: 'unknown',
292
- recommendedAction: 'deploy'
293
- };
294
- }
295
-
296
- // Interactive confirmation (unless force is enabled)
297
- if (!options.force) {
298
- const originalDomain = domain;
299
- let domainSelected = false;
300
- while (!domainSelected) {
301
- const confirm = await askChoice(`\nReady to deploy ${domain}?`, ['Yes, proceed with deployment', 'Choose different domain', 'Cancel deployment'], 0);
302
- if (confirm === 0) {
303
- // Yes, proceed
304
- domainSelected = true;
305
- } else if (confirm === 1) {
306
- // Choose different domain
307
- const availableDomains = await this.discoverAvailableDomains();
308
- if (availableDomains.length <= 1) {
309
- // No other domains available
310
- const createNew = await askChoice('No other domains available. What would you like to do?', ['Create a new service', 'Go back to deployment options', 'Cancel deployment'], 0);
311
- if (createNew === 0) {
312
- // Create new service
313
- let serviceName;
314
- let validServiceName = false;
315
- while (!validServiceName) {
316
- serviceName = await askUser('Enter service name (lowercase letters, numbers, hyphens only):');
317
- if (!serviceName || serviceName.trim() === '') {
318
- this.logOutput('❌ Service name is required', 'error');
319
- continue;
320
- }
321
-
322
- // Validate service name format
323
- if (!/^[a-z0-9-]+$/.test(serviceName.trim())) {
324
- this.logOutput('❌ Service name must contain only lowercase letters, numbers, and hyphens', 'error');
325
- this.logOutput('💡 Example: data-service, user-auth, content-api', 'info');
326
- continue;
327
- }
328
- validServiceName = true;
329
- serviceName = serviceName.trim();
330
- }
331
- try {
332
- this.logOutput(`🏗️ Creating new service: ${serviceName}`, 'info');
333
-
334
- // Also ask for domain name
335
- const domainName = await askUser('Enter domain name for this service (e.g., api.example.com):');
336
- if (!domainName || domainName.trim() === '') {
337
- this.logOutput('❌ Domain name is required', 'error');
338
- continue;
339
- }
340
-
341
- // Run service initialization using spawn with absolute path
342
- const {
343
- spawn
344
- } = await import('child_process');
345
- const initScriptPath = join(process.cwd(), 'bin', 'service-management', 'init-service.js');
346
- const initProcess = spawn('node', [initScriptPath, serviceName, '--domains', domainName, '--output', process.cwd()], {
347
- stdio: 'inherit',
348
- cwd: process.cwd()
349
- });
350
- await new Promise((resolve, reject) => {
351
- initProcess.on('close', code => {
352
- if (code === 0) {
353
- resolve();
354
- } else {
355
- reject(new Error(`Service initialization failed with code ${code}`));
356
- }
357
- });
358
- initProcess.on('error', reject);
359
- });
360
- this.logOutput(`✅ Service ${serviceName} created successfully!`, 'success');
361
-
362
- // Re-discover domains now that we have a new service
363
- this.logOutput('🔄 Re-discovering available domains...', 'info');
364
- const updatedDomains = await this.discoverAvailableDomains();
365
- if (updatedDomains.length > 0) {
366
- domain = await this.selectDomainInteractively();
367
- this.logOutput(`🚀 Enterprise deployment: ${domain}`, 'info');
368
- } else {
369
- this.logOutput('❌ No domains found after service creation', 'error');
370
- return;
371
- }
372
- } catch (error) {
373
- this.logOutput(`❌ Failed to create service: ${error.message}`, 'error');
374
- continue;
375
- }
376
- } else if (createNew === 1) {
377
- // Go back - continue the loop
378
- continue;
379
- } else {
380
- // Cancel
381
- this.logOutput('❌ Deployment cancelled by user', 'warn');
382
- return;
383
- }
384
- } else {
385
- // Multiple domains available, let user choose
386
- domain = await this.selectDomainInteractively();
387
- this.logOutput(`🚀 Enterprise deployment: ${domain}`, 'info');
388
- }
389
- } else {
390
- // Cancel
391
- this.logOutput('❌ Deployment cancelled by user', 'warn');
392
- return;
393
- }
394
- }
395
- }
396
- const deploymentId = this.generateDeploymentId();
397
- const auditor = this.modules.auditor;
398
-
399
- // Start audit session
400
- const deploymentContext = auditor.startDeploymentAudit(deploymentId, domain, {
401
- environment: options.env,
402
- cliMode: true,
403
- options
404
- });
405
-
406
- // Validation phase
407
- if (!options.force) {
408
- this.logOutput('🔍 Running validation...', 'info');
409
- const validation = await this.modules.validator.validateDeployment(domain, {
410
- environment: options.env,
411
- validationLevel: options.validation,
412
- deploymentType: domainVerification.domainStatus,
413
- // 'available', 'update', etc.
414
- skipEndpointCheck: domainVerification.domainStatus === 'available'
415
- });
416
- if (validation.overall !== 'passed') {
417
- this.logOutput('❌ Validation failed:', 'error');
418
- validation.errors.forEach(error => this.logOutput(` - ${error.message}`, 'error'));
419
- if (!options.force) {
420
- process.exit(1);
421
- }
422
- }
423
- }
424
-
425
- // Execute deployment - Create domain-specific orchestrator
426
- const domainOrchestrator = new MultiDomainOrchestrator({
427
- domains: [domain],
428
- environment: options.env,
429
- dryRun: options.dryRun,
430
- parallelDeployments: 1,
431
- enableRollback: options.rollback !== false
432
- });
433
- await domainOrchestrator.initialize();
434
- const deploymentResult = await domainOrchestrator.deploySingleDomain(domain);
435
-
436
- // Run tests if enabled
437
- if (options.tests !== false && deploymentResult.url) {
438
- this.logOutput('🧪 Running production tests...', 'info');
439
- this.logOutput('⏳ Waiting for deployment to propagate...', 'info');
440
-
441
- // Wait for deployment to propagate (especially important for new services)
442
- await new Promise(resolve => setTimeout(resolve, 10000)); // 10 second delay
443
-
444
- const deploymentUrl = deploymentResult.url;
445
- const testResult = await this.modules.productionTester.runFullTestSuite(options.env);
446
- if (testResult.failed > 0) {
447
- this.logOutput(`⚠️ ${testResult.failed}/${testResult.total} tests failed`, 'warn');
448
- this.logOutput('💡 Note: Some test failures may be expected for new deployments during DNS propagation', 'info');
449
- } else {
450
- this.logOutput(`✅ All ${testResult.total} tests passed`, 'success');
451
- }
452
- } else if (options.tests !== false && !deploymentResult.url) {
453
- this.logOutput('⏭️ Skipping tests - no deployment URL available', 'warn');
454
- }
455
-
456
- // End audit session
457
- auditor.endDeploymentAudit(deploymentId, 'success', {
458
- url: deploymentResult.url,
459
- duration: deploymentResult.duration
460
- });
461
- this.logOutput(`✅ Deployment successful: ${deploymentResult.url}`, 'success');
462
- if (this.globalConfig.outputFormat !== 'minimal') {
463
- console.log('\\n📊 Deployment Summary:');
464
- console.log(` 🆔 ID: ${deploymentId}`);
465
- console.log(` 🌐 Domain: ${domain}`);
466
- console.log(` 🌍 Environment: ${options.env}`);
467
- console.log(` 🔗 URL: ${deploymentResult.url}`);
468
- console.log(` ⏱️ Duration: ${deploymentResult.duration}s`);
469
- }
470
- } catch (error) {
471
- this.logOutput(`❌ Deployment failed: ${error.message}`, 'error');
472
- process.exit(1);
473
- }
474
- }
475
-
476
- /**
477
- * Deploy multiple domains
478
- */
479
- async deployMultiDomain(domains, options) {
480
- try {
481
- this.logOutput(`🌍 Multi-domain deployment: ${domains.length} domains`, 'info');
482
- const coordinationResult = await this.modules.coordinator.coordinateMultiDomainDeployment(domains, {
483
- environment: options.env,
484
- batchSize: parseInt(options.batchSize),
485
- enableCoordination: options.coordination,
486
- sharedSecrets: options.sharedSecrets,
487
- resolveDependencies: options.dependencyOrder,
488
- dryRun: options.dryRun
489
- });
490
- this.logOutput(`✅ Multi-domain deployment completed`, 'success');
491
- console.log(` ✅ Successful: ${coordinationResult.results.successful.length}`);
492
- console.log(` ❌ Failed: ${coordinationResult.results.failed.length}`);
493
- } catch (error) {
494
- this.logOutput(`❌ Multi-domain deployment failed: ${error.message}`, 'error');
495
- process.exit(1);
496
- }
497
- }
498
-
499
- /**
500
- * Deploy portfolio
501
- */
502
- async deployPortfolio(options) {
503
- try {
504
- this.logOutput('📊 Portfolio deployment', 'info');
505
-
506
- // Discover portfolio first
507
- const portfolio = await this.modules.coordinator.discoverPortfolio();
508
- let domains = portfolio.domains.map(d => d.name || d.domain);
509
-
510
- // Apply filters
511
- if (options.filter) {
512
- const filterRegex = new RegExp(options.filter);
513
- domains = domains.filter(domain => filterRegex.test(domain));
514
- }
515
- if (options.exclude) {
516
- const excludeRegex = new RegExp(options.exclude);
517
- domains = domains.filter(domain => !excludeRegex.test(domain));
518
- }
519
- this.logOutput(`📋 Deploying ${domains.length} domains from portfolio`, 'info');
520
-
521
- // Health check if requested
522
- if (options.healthCheck) {
523
- this.logOutput('❤️ Running pre-deployment health checks...', 'info');
524
- const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
525
- this.logOutput(`📊 Health: ${healthResults.summary.healthy}/${healthResults.summary.total} healthy`, 'info');
526
- }
527
-
528
- // Execute portfolio deployment
529
- const result = await this.modules.coordinator.coordinateMultiDomainDeployment(domains, {
530
- environment: options.env,
531
- rollbackThreshold: parseFloat(options.rollbackThreshold),
532
- dryRun: options.dryRun
533
- });
534
- this.logOutput('✅ Portfolio deployment completed', 'success');
535
- } catch (error) {
536
- this.logOutput(`❌ Portfolio deployment failed: ${error.message}`, 'error');
537
- process.exit(1);
538
- }
539
- }
540
-
541
- /**
542
- * Discover domain configuration
543
- */
544
- async discoverDomain(domain, options) {
545
- try {
546
- this.logOutput(`🔍 Discovering configuration for: ${domain}`, 'info');
547
- const discoveredConfig = await this.modules.domainDiscovery.discoverDomainConfig(domain, {
548
- cloudflareToken: options.token,
549
- useCache: options.cache,
550
- updateDomainsJs: options.updateConfig
551
- });
552
- this.logOutput('✅ Discovery completed', 'success');
553
- if (this.globalConfig.outputFormat !== 'minimal') {
554
- console.log('\\n📋 Discovered Configuration:');
555
- console.log(JSON.stringify(discoveredConfig, null, 2));
556
- }
557
- } catch (error) {
558
- this.logOutput(`❌ Discovery failed: ${error.message}`, 'error');
559
- process.exit(1);
560
- }
561
- }
562
-
563
- /**
564
- * Validate domain
565
- */
566
- async validateDomain(domain, options) {
567
- try {
568
- this.logOutput(`🔍 Validating: ${domain}`, 'info');
569
- const validation = await this.modules.validator.validateDeploymentReadiness(domain, {
570
- environment: options.env,
571
- validationLevel: options.level
572
- });
573
- if (validation.valid) {
574
- this.logOutput('✅ Validation passed', 'success');
575
- } else {
576
- this.logOutput('❌ Validation failed:', 'error');
577
- validation.errors.forEach(error => this.logOutput(` - ${error}`, 'error'));
578
- if (validation.warnings?.length > 0) {
579
- this.logOutput('⚠️ Warnings:', 'warn');
580
- validation.warnings.forEach(warning => this.logOutput(` - ${warning}`, 'warn'));
581
- }
582
- process.exit(1);
583
- }
584
- } catch (error) {
585
- this.logOutput(`❌ Validation error: ${error.message}`, 'error');
586
- process.exit(1);
587
- }
588
- }
589
-
590
- /**
591
- * Test domain
592
- */
593
- async testDomain(domain, options) {
594
- try {
595
- this.logOutput(`🧪 Testing: ${domain}`, 'info');
596
- const url = options.url || this.getDomainUrl(domain);
597
- const testSuites = options.suites.split(',');
598
- const testResult = await this.modules.productionTester.runFullTestSuite(options.env || 'production');
599
- if (testResult.failed === 0) {
600
- this.logOutput(`✅ All ${testResult.total} tests passed`, 'success');
601
- } else {
602
- this.logOutput(`❌ ${testResult.failed}/${testResult.total} tests failed`, 'error');
603
- process.exit(1);
604
- }
605
- } catch (error) {
606
- this.logOutput(`❌ Testing failed: ${error.message}`, 'error');
607
- process.exit(1);
608
- }
609
- }
610
-
611
- /**
612
- * Generate secrets for domain
613
- */
614
- async generateSecrets(domain, options) {
615
- try {
616
- this.logOutput(`🔐 Generating secrets for: ${domain}`, 'info');
617
- const formats = options.formats.split(',');
618
- const secretResult = await this.modules.secretManager.generateDomainSpecificSecrets(domain, options.env, {
619
- formats,
620
- coordinate: options.coordinate,
621
- deployToCloudflare: options.deploy
622
- });
623
- this.logOutput(`✅ Generated ${Object.keys(secretResult.secrets).length} secrets`, 'success');
624
- if (this.globalConfig.outputFormat !== 'minimal') {
625
- console.log('\\n🔑 Generated Secrets:');
626
- Object.keys(secretResult.secrets).forEach(key => {
627
- console.log(` - ${key}: ${secretResult.secrets[key].substring(0, 8)}...`);
628
- });
629
- }
630
- } catch (error) {
631
- this.logOutput(`❌ Secret generation failed: ${error.message}`, 'error');
632
- process.exit(1);
633
- }
634
- }
635
-
636
- /**
637
- * Monitor portfolio health
638
- */
639
- async monitorPortfolio(options) {
640
- try {
641
- this.logOutput('📊 Starting portfolio monitoring...', 'info');
642
- if (options.continuous) {
643
- const interval = parseInt(options.interval);
644
- const runHealthCheck = async () => {
645
- const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
646
- this.logOutput(`📊 Health: ${healthResults.summary.healthy}/${healthResults.summary.total} healthy`, 'info');
647
- if (healthResults.summary.unhealthy > 0 && options.alertWebhook) {
648
- // Send alert (implementation would send to webhook)
649
- this.logOutput(`🚨 Alert: ${healthResults.summary.unhealthy} domains unhealthy`, 'warn');
650
- }
651
- };
652
-
653
- // Initial check
654
- await runHealthCheck();
655
-
656
- // Continuous monitoring
657
- setInterval(runHealthCheck, interval);
658
- this.logOutput(`🔄 Continuous monitoring enabled (interval: ${interval}ms)`, 'info');
659
- } else {
660
- // One-time health check
661
- const healthResults = await this.modules.coordinator.monitorPortfolioHealth();
662
- this.logOutput('✅ Portfolio health check completed', 'success');
663
- console.log(` 📊 Total: ${healthResults.summary.total}`);
664
- console.log(` ✅ Healthy: ${healthResults.summary.healthy}`);
665
- console.log(` ❌ Unhealthy: ${healthResults.summary.unhealthy}`);
666
- console.log(` 🔥 Errors: ${healthResults.summary.errors}`);
667
- }
668
- } catch (error) {
669
- this.logOutput(`❌ Monitoring failed: ${error.message}`, 'error');
670
- process.exit(1);
671
- }
672
- }
673
-
674
- /**
675
- * Get domain URL for testing
676
- */
677
- getDomainUrl(domain) {
678
- // Generate standard URL pattern
679
- const domainKey = domain.replace(/\\./g, '');
680
- return `https://${domainKey}-data-service.tamylatrading.workers.dev`;
681
- }
682
-
683
- /**
684
- * Generate deployment ID
685
- */
686
- generateDeploymentId() {
687
- const timestamp = Date.now().toString(36);
688
- const random = Math.random().toString(36).substr(2, 9);
689
- return `cli_${timestamp}_${random}`;
690
- }
691
-
692
- /**
693
- * Log output with different levels
694
- */
695
- logOutput(message, level = 'info') {
696
- if (program.opts().quiet && level !== 'error') return;
697
- const colors = {
698
- info: '\\x1b[36m',
699
- // Cyan
700
- success: '\\x1b[32m',
701
- // Green
702
- warn: '\\x1b[33m',
703
- // Yellow
704
- error: '\\x1b[31m',
705
- // Red
706
- reset: '\\x1b[0m' // Reset
707
- };
708
- const useColor = !program.opts().noColor;
709
- const colorCode = useColor ? colors[level] || colors.info : '';
710
- const resetCode = useColor ? colors.reset : '';
711
- console.log(`${colorCode}${message}${resetCode}`);
712
- }
713
-
714
- /**
715
- * Placeholder implementations for remaining methods
716
- */
717
- async discoverPortfolio(options) {
718
- this.logOutput('🔍 Portfolio discovery not yet implemented', 'warn');
719
- }
720
- async validatePortfolio(options) {
721
- this.logOutput('🔍 Portfolio validation not yet implemented', 'warn');
722
- }
723
- async testPortfolio(options) {
724
- this.logOutput('🧪 Portfolio testing not yet implemented', 'warn');
725
- }
726
- async migrateDomain(domain, options) {
727
- this.logOutput(`🗄️ Database migration for ${domain} not yet implemented`, 'warn');
728
- }
729
- async migrateAll(options) {
730
- this.logOutput('🗄️ Bulk database migration not yet implemented', 'warn');
731
- }
732
- async coordinateSecrets(domains, options) {
733
- this.logOutput(`🔐 Secret coordination for ${domains.length} domains not yet implemented`, 'warn');
734
- }
735
- async rollbackDomain(domain, options) {
736
- this.logOutput(`🔄 Domain rollback for ${domain} not yet implemented`, 'warn');
737
- }
738
- async rollbackPortfolio(options) {
739
- this.logOutput('🔄 Portfolio rollback not yet implemented', 'warn');
740
- }
741
- async getStatus(domain, options) {
742
- this.logOutput(`📊 Status check for ${domain || 'portfolio'} not yet implemented`, 'warn');
743
- }
744
- async auditDomain(domain, options) {
745
- this.logOutput(`📋 Audit report for ${domain} not yet implemented`, 'warn');
746
- }
747
- async auditPortfolio(options) {
748
- this.logOutput('📋 Portfolio audit not yet implemented', 'warn');
749
- }
750
- async manageConfigCache(domain, options) {
751
- this.logOutput(`⚙️ Config cache management for ${domain} not yet implemented`, 'warn');
752
- }
753
- async listDomains(options) {
754
- this.logOutput('📋 Discovering available domains...', 'info');
755
- const domains = await this.discoverAvailableDomains();
756
- if (domains.length === 0) {
757
- this.logOutput('❌ No domains found in services directory', 'error');
758
- this.logOutput('💡 Create a service first using: node bin/service-management/init-service.js', 'info');
759
- return;
760
- }
761
- if (options.format === 'json') {
762
- console.log(JSON.stringify({
763
- domains,
764
- count: domains.length
765
- }, null, 2));
766
- } else if (options.format === 'yaml') {
767
- console.log('domains:');
768
- domains.forEach(domain => console.log(` - ${domain}`));
769
- console.log(`count: ${domains.length}`);
770
- } else {
771
- // Table format (default)
772
- this.logOutput(`📋 Found ${domains.length} domain(s):`, 'success');
773
- console.log('');
774
- console.log('┌─────────────────────────────────────┐');
775
- console.log('│ Domain │');
776
- console.log('├─────────────────────────────────────┤');
777
- domains.forEach(domain => {
778
- console.log(`│ ${domain.padEnd(35)} │`);
779
- });
780
- console.log('└─────────────────────────────────────┘');
781
- }
782
- }
783
-
784
- /**
785
- * Discover available domains from services directory
786
- */
787
- async discoverAvailableDomains() {
788
- const domains = new Set();
789
- try {
790
- const servicesPath = join(process.cwd(), 'services');
791
- const fs = await import('fs/promises');
792
-
793
- // Check if services directory exists
794
- try {
795
- await fs.access(servicesPath);
796
- } catch {
797
- this.logOutput('⚠️ No services directory found', 'warn');
798
- return [];
799
- }
800
-
801
- // Read service directories
802
- const serviceDirs = await fs.readdir(servicesPath, {
803
- withFileTypes: true
804
- });
805
- for (const dir of serviceDirs) {
806
- if (!dir.isDirectory()) continue;
807
- const servicePath = join(servicesPath, dir.name);
808
- const wranglerPath = join(servicePath, 'wrangler.toml');
809
- try {
810
- // Check if wrangler.toml exists
811
- await fs.access(wranglerPath);
812
-
813
- // Read and parse wrangler.toml
814
- const content = await fs.readFile(wranglerPath, 'utf-8');
815
- const domainMatch = content.match(/DOMAIN_NAME\s*=\s*["']([^"']+)["']/);
816
- if (domainMatch) {
817
- domains.add(domainMatch[1]);
818
- }
819
- } catch {
820
- // Skip services without wrangler.toml or domain config
821
- continue;
822
- }
823
- }
824
- } catch (error) {
825
- this.logOutput(`❌ Error discovering domains: ${error.message}`, 'error');
826
- }
827
- return Array.from(domains).sort();
828
- }
829
-
830
- /**
831
- * Interactively select a domain from available options
832
- */
833
- async selectDomainInteractively() {
834
- this.logOutput('🔍 Discovering available domains...', 'info');
835
- const domains = await this.discoverAvailableDomains();
836
- if (domains.length === 0) {
837
- this.logOutput('❌ No domains found in services. Please create a service first or specify domain manually.', 'error');
838
- process.exit(1);
839
- }
840
- if (domains.length === 1) {
841
- const domain = domains[0];
842
- this.logOutput(`✅ Only one domain found: ${domain}`, 'success');
843
- return domain;
844
- }
845
- this.logOutput(`📋 Found ${domains.length} available domains:`, 'info');
846
- domains.forEach((domain, index) => {
847
- console.log(` ${index + 1}. ${domain}`);
848
- });
849
- const choice = await askChoice('Select a domain to deploy:', domains);
850
- const selectedDomain = domains[choice];
851
- this.logOutput(`✅ Selected domain: ${selectedDomain}`, 'success');
852
- return selectedDomain;
853
- }
854
- async cleanupDeployments(options) {
855
- this.logOutput('🧹 Deployment cleanup not yet implemented', 'warn');
856
- }
857
- }
858
-
859
- // Initialize and run CLI
860
- const cli = new EnterpriseDeploymentCLI();
861
-
862
- // Set up commands first (before heavy module initialization)
863
- cli.setupCommands();
864
-
865
- // Parse command line arguments
866
- program.parse();
867
-
868
- // Handle unhandled errors
869
- process.on('uncaughtException', error => {
870
- console.error('❌ Uncaught Exception:', error.message);
871
- process.exit(1);
872
- });
873
- process.on('unhandledRejection', (reason, promise) => {
874
- console.error('❌ Unhandled Rejection at:', promise, 'reason:', reason);
875
- process.exit(1);
876
- });
877
- export { EnterpriseDeploymentCLI };