@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
@@ -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 };