@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
@@ -8,32 +8,49 @@
8
8
  * - Gathers credentials smartly: env vars → flags → interactive collection with auto-fetch
9
9
  * - Validates token and fetches account ID & zone ID from Cloudflare
10
10
  * - REFACTORED (Task 3.2): Integrates with MultiDomainOrchestrator for full deployment orchestration
11
+ * - REFACTORED (UX): Modularized with helper functions for better maintainability
11
12
  */
12
13
 
13
14
  import chalk from 'chalk';
14
- import { resolve } from 'path';
15
- import { ManifestLoader } from '../shared/config/manifest-loader.js';
16
- import { CloudflareServiceValidator } from '../shared/config/cloudflare-service-validator.js';
17
- import { DeploymentCredentialCollector } from '../shared/deployment/credential-collector.js';
18
- import { StandardOptions } from '../shared/utils/cli-options.js';
19
- import { ConfigLoader } from '../shared/utils/config-loader.js';
20
- import { DomainRouter } from '../shared/routing/domain-router.js';
21
- import { MultiDomainOrchestrator } from "../../orchestration/multi-domain-orchestrator.js";
15
+ import { resolve, join } from 'path';
16
+ import { existsSync } from 'fs';
17
+ import { ManifestLoader } from '../lib/shared/config/manifest-loader.js';
18
+ import { CloudflareServiceValidator } from '../lib/shared/config/cloudflare-service-validator.js';
19
+ import { DeploymentCredentialCollector } from '../lib/shared/deployment/credential-collector.js';
20
+ import { StandardOptions } from '../lib/shared/utils/cli-options.js';
21
+ import { ConfigLoader } from '../lib/shared/utils/config-loader.js';
22
+ import { DomainRouter } from '../lib/shared/routing/domain-router.js';
23
+ import { MultiDomainOrchestrator } from '../orchestration/multi-domain-orchestrator.js';
24
+
25
+ // Import modular helpers
26
+ import { detectExistingResources, displayDeploymentPlan } from './helpers/resource-detection.js';
27
+ import { confirmDeployment, displayDeploymentResults, displayNextSteps } from './helpers/deployment-ui.js';
28
+ import { runPostDeploymentVerification } from './helpers/deployment-verification.js';
29
+ import { handleDeploymentError } from './helpers/error-recovery.js';
22
30
  export function registerDeployCommand(program) {
23
31
  const command = program.command('deploy').description('Deploy a Clodo service with smart credential handling and domain selection')
24
32
  // Cloudflare-specific options
25
- .option('--token <token>', 'Cloudflare API token').option('--account-id <id>', 'Cloudflare account ID').option('--zone-id <id>', 'Cloudflare zone ID').option('--domain <domain>', 'Specific domain to deploy to (otherwise prompted if multiple exist)').option('--environment <env>', 'Target environment (development, staging, production)', 'production').option('--all-domains', 'Deploy to all configured domains (ignores --domain flag)').option('--dry-run', 'Simulate deployment without making changes').option('--service-path <path>', 'Path to service directory', '.');
33
+ .option('--token <token>', 'Cloudflare API token').option('--account-id <id>', 'Cloudflare account ID').option('--zone-id <id>', 'Cloudflare zone ID').option('--domain <domain>', 'Specific domain to deploy to (otherwise prompted if multiple exist)').option('--environment <env>', 'Target environment (development, staging, production)', 'production').option('--development', 'Deploy to development environment (shorthand for --environment development)').option('--staging', 'Deploy to staging environment (shorthand for --environment staging)').option('--production', 'Deploy to production environment (shorthand for --environment production)').option('--all-domains', 'Deploy to all configured domains (ignores --domain flag)').option('--dry-run', 'Simulate deployment without making changes').option('-y, --yes', 'Skip confirmation prompts (for CI/CD)').option('--service-path <path>', 'Path to service directory', '.');
26
34
 
27
35
  // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
28
36
  StandardOptions.define(command).action(async options => {
29
37
  try {
30
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
38
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options);
31
39
  const configLoader = new ConfigLoader({
32
40
  verbose: options.verbose,
33
41
  quiet: options.quiet,
34
42
  json: options.json
35
43
  });
36
44
 
45
+ // Handle shorthand environment flags
46
+ if (options.development) {
47
+ options.environment = 'development';
48
+ } else if (options.staging) {
49
+ options.environment = 'staging';
50
+ } else if (options.production) {
51
+ options.environment = 'production';
52
+ }
53
+
37
54
  // Load config from file if specified
38
55
  let configFileData = {};
39
56
  if (options.configFile) {
@@ -68,7 +85,7 @@ export function registerDeployCommand(program) {
68
85
  CloudflareServiceValidator.printValidationReport(serviceConfig.validationResult.validation);
69
86
  }
70
87
  ManifestLoader.printManifestInfo(serviceConfig.manifest);
71
- output.info(`Configuration loaded from: ${serviceConfig.foundAt}`);
88
+ console.log(chalk.blue(`ℹ️ Configuration loaded from: ${serviceConfig.foundAt}`));
72
89
 
73
90
  // Step 2: Smart credential gathering with interactive collection
74
91
  // Uses DeploymentCredentialCollector which:
@@ -121,20 +138,36 @@ export function registerDeployCommand(program) {
121
138
  }).filter(d => d !== null);
122
139
  }
123
140
 
124
- // If no domains in config, try to detect from environment
141
+ // If no domains in manifest but we have a selected zone from credentials, use that
142
+ if (detectedDomains.length === 0 && credentials.zoneName) {
143
+ detectedDomains = [credentials.zoneName];
144
+ if (!options.quiet) {
145
+ console.log(chalk.blue(`ℹ️ Using selected Cloudflare domain: ${credentials.zoneName}`));
146
+ }
147
+ }
148
+
149
+ // If still no domains and it's a detected CF service, use default
125
150
  if (detectedDomains.length === 0 && manifest._source === 'cloudflare-service-detected') {
126
151
  // For detected CF services, use default
127
152
  detectedDomains = ['workers.cloudflare.com'];
153
+ if (!options.quiet) {
154
+ console.log(chalk.blue(`ℹ️ No custom domains configured, using default: workers.cloudflare.com`));
155
+ }
156
+ } else if (detectedDomains.length > 0 && !options.quiet && !credentials.zoneName) {
157
+ console.log(chalk.blue(`ℹ️ Found ${detectedDomains.length} configured domain(s) in manifest`));
128
158
  }
129
159
 
130
160
  // Domain selection: check CLI flag first, then prompt user
131
161
  let selectedDomain = mergedOptions.domain;
162
+ if (selectedDomain && !options.quiet) {
163
+ console.log(chalk.blue(`ℹ️ Using domain from --domain flag: ${selectedDomain}`));
164
+ }
132
165
  if (!selectedDomain && detectedDomains.length > 0) {
133
166
  if (detectedDomains.length === 1) {
134
167
  // Only one domain, use it directly
135
168
  selectedDomain = detectedDomains[0];
136
169
  if (!options.quiet) {
137
- console.log(chalk.green(`✓ Selected domain: ${selectedDomain}`));
170
+ console.log(chalk.green(`✓ Auto-selected only available domain: ${selectedDomain}`));
138
171
  }
139
172
  } else {
140
173
  // Multiple domains available - let user choose
@@ -197,24 +230,58 @@ export function registerDeployCommand(program) {
197
230
  const serviceName = manifest.serviceName || 'unknown-service';
198
231
  const serviceType = manifest.serviceType || 'generic';
199
232
 
200
- // Display deployment plan
201
- console.log(chalk.cyan('\n📋 Deployment Plan:'));
202
- console.log(chalk.gray('─'.repeat(60)));
203
- console.log(chalk.white(`Service: ${serviceName}`));
204
- console.log(chalk.white(`Type: ${serviceType}`));
205
- console.log(chalk.white(`Domain: ${selectedDomain}`));
206
- console.log(chalk.white(`Environment: ${mergedOptions.environment || 'production'}`));
207
- console.log(chalk.white(`Account: ${credentials.accountId.substring(0, 8)}...`));
208
- console.log(chalk.white(`Zone: ${credentials.zoneId.substring(0, 8)}...`));
209
- console.log(chalk.white(`Deployment Mode: ${options.dryRun ? 'DRY RUN' : 'LIVE'}`));
210
- console.log(chalk.gray('─'.repeat(60)));
211
- if (options.dryRun) {
212
- console.log(chalk.yellow('\n🔍 DRY RUN MODE - No changes will be made\n'));
233
+ // Step 5: Detect existing resources and display deployment plan
234
+ const {
235
+ existingWorker,
236
+ existingDatabases,
237
+ resourceDetectionFailed
238
+ } = await detectExistingResources(serviceName, manifest, credentials, output, options.verbose);
239
+ displayDeploymentPlan({
240
+ serviceName,
241
+ serviceType,
242
+ selectedDomain,
243
+ environment: mergedOptions.environment,
244
+ credentials,
245
+ dryRun: options.dryRun,
246
+ existingWorker,
247
+ existingDatabases,
248
+ resourceDetectionFailed,
249
+ manifest
250
+ });
251
+
252
+ // Step 6: Get user confirmation
253
+ const confirmed = await confirmDeployment(options);
254
+ if (!confirmed) {
255
+ process.exit(0);
213
256
  }
214
257
 
215
258
  // Step 5: Initialize MultiDomainOrchestrator for deployment
216
259
  // REFACTORED (Task 3.2): Direct orchestrator integration instead of external deployer
217
260
  console.log(chalk.cyan('\n⚙️ Initializing orchestration system...\n'));
261
+
262
+ // Determine wrangler config path based on selected domain/zone
263
+ // For multi-customer deployments, use customer-specific config if available
264
+ let wranglerConfigPath;
265
+ const configDir = join(servicePath, 'config');
266
+
267
+ // Map domain to config file (customize this mapping for your setup)
268
+ if (selectedDomain === 'clodo.dev' || credentials.cloudflareSettings?.zoneName === 'clodo.dev') {
269
+ // Use config/wrangler.toml for clodo.dev domain
270
+ const clodoConfigPath = join(configDir, 'wrangler.toml');
271
+ if (existsSync(clodoConfigPath)) {
272
+ wranglerConfigPath = clodoConfigPath;
273
+ console.log(chalk.green(`✓ Using clodo.dev config: ${clodoConfigPath}`));
274
+ }
275
+ }
276
+ // Add more domain mappings as needed:
277
+ // else if (selectedDomain === 'customer2.com') {
278
+ // wranglerConfigPath = path.join(configDir, 'customers', 'customer2-wrangler.toml');
279
+ // }
280
+
281
+ // If no specific config found, use default (root wrangler.toml)
282
+ if (!wranglerConfigPath) {
283
+ console.log(chalk.yellow(`ℹ Using default wrangler.toml from service root`));
284
+ }
218
285
  const orchestrator = new MultiDomainOrchestrator({
219
286
  domains: [selectedDomain],
220
287
  environment: mergedOptions.environment || 'production',
@@ -223,8 +290,12 @@ export function registerDeployCommand(program) {
223
290
  parallelDeployments: 1,
224
291
  // Single domain in this flow
225
292
  servicePath: servicePath,
226
- cloudflareToken: credentials.token,
227
- cloudflareAccountId: credentials.accountId,
293
+ serviceName: serviceName,
294
+ // Pass service name for custom domain construction
295
+ wranglerConfigPath: wranglerConfigPath,
296
+ // Pass custom config path if found
297
+ // Use cloudflareSettings object for complete zone-specific configuration
298
+ cloudflareSettings: credentials.cloudflareSettings,
228
299
  enablePersistence: !options.dryRun,
229
300
  rollbackEnabled: !options.dryRun,
230
301
  verbose: options.verbose
@@ -240,7 +311,7 @@ export function registerDeployCommand(program) {
240
311
  process.exit(1);
241
312
  }
242
313
 
243
- // Step 6: Execute deployment via orchestrator
314
+ // Step 7: Execute deployment via orchestrator
244
315
  console.log(chalk.cyan('🚀 Starting deployment via orchestrator...\n'));
245
316
  let result;
246
317
  try {
@@ -251,71 +322,32 @@ export function registerDeployCommand(program) {
251
322
  environment: mergedOptions.environment || 'production'
252
323
  });
253
324
  } catch (deployError) {
254
- console.error(chalk.red('\n❌ Deployment failed during orchestration\n'));
255
- console.error(chalk.yellow(`Error: ${deployError.message}`));
256
-
257
- // Provide helpful error context
258
- if (deployError.message.includes('credentials') || deployError.message.includes('auth')) {
259
- console.error(chalk.yellow('\n💡 Credential Issue:'));
260
- console.error(chalk.white(' Check your API token, account ID, and zone ID'));
261
- console.error(chalk.white(' Visit: https://dash.cloudflare.com/profile/api-tokens'));
262
- }
263
- if (deployError.message.includes('domain') || deployError.message.includes('zone')) {
264
- console.error(chalk.yellow('\n� Domain Issue:'));
265
- console.error(chalk.white(' Verify domain exists in Cloudflare'));
266
- console.error(chalk.white(' Check API token has zone:read permissions'));
267
- }
268
- if (process.env.DEBUG) {
269
- console.error(chalk.gray('\nFull Stack Trace:'));
270
- console.error(chalk.gray(deployError.stack));
271
- }
272
- process.exit(1);
325
+ await handleDeploymentError(deployError, command, options);
273
326
  }
274
327
 
275
- // Step 7: Display deployment results
276
- console.log(chalk.green('\n✅ Deployment Completed Successfully!\n'));
277
- console.log(chalk.gray('─'.repeat(60)));
278
-
279
- // Display results from orchestrator
280
- if (result.url) {
281
- console.log(chalk.white(`🌐 Service URL: ${chalk.bold(result.url)}`));
282
- }
283
- console.log(chalk.white(`📦 Service: ${serviceName}`));
284
- console.log(chalk.white(`🔧 Type: ${serviceType}`));
285
- console.log(chalk.white(`🌍 Domain: ${selectedDomain}`));
286
- console.log(chalk.white(`🌎 Environment: ${mergedOptions.environment || 'production'}`));
287
- if (result.workerId) {
288
- console.log(chalk.white(`👤 Worker ID: ${result.workerId}`));
289
- }
290
- if (result.deploymentId) {
291
- console.log(chalk.white(`📋 Deployment ID: ${result.deploymentId}`));
292
- }
293
- if (result.status) {
294
- const statusColor = result.status.toLowerCase().includes('success') ? chalk.green : chalk.yellow;
295
- console.log(chalk.white(`📊 Status: ${statusColor(result.status)}`));
296
- }
328
+ // Step 8: Display deployment results
329
+ displayDeploymentResults({
330
+ result,
331
+ serviceName,
332
+ serviceType,
333
+ selectedDomain,
334
+ environment: mergedOptions.environment
335
+ });
297
336
 
298
- // Display audit information if available
299
- if (result.auditLog) {
300
- console.log(chalk.cyan('\n📋 Deployment Audit:'));
301
- console.log(chalk.gray(` Started: ${result.auditLog.startTime}`));
302
- console.log(chalk.gray(` Completed: ${result.auditLog.endTime}`));
303
- console.log(chalk.gray(` Duration: ${result.auditLog.duration}ms`));
304
- }
305
- console.log(chalk.gray('─'.repeat(60)));
337
+ // Step 9: Run post-deployment verification and health check
338
+ await runPostDeploymentVerification(serviceName, result, credentials, {
339
+ ...options,
340
+ serviceName,
341
+ customDomain: selectedDomain !== 'workers.cloudflare.com' ? selectedDomain : null
342
+ });
306
343
 
307
- // Display next steps
308
- if (!options.dryRun) {
309
- console.log(chalk.cyan('\n💡 Next Steps:'));
310
- console.log(chalk.white(` • Test deployment: curl ${result.url || `https://${selectedDomain}`}`));
311
- console.log(chalk.white(` • View logs: wrangler tail ${serviceName}`));
312
- console.log(chalk.white(` • Monitor: https://dash.cloudflare.com`));
313
- console.log(chalk.white(` • Check audit logs: See deployment ID above\n`));
314
- } else {
315
- console.log(chalk.cyan('\n💡 Dry Run Complete'));
316
- console.log(chalk.white(` • Review the plan above`));
317
- console.log(chalk.white(` • Remove --dry-run to execute deployment\n`));
318
- }
344
+ // Step 10: Display next steps
345
+ displayNextSteps({
346
+ result,
347
+ selectedDomain,
348
+ serviceName,
349
+ dryRun: options.dryRun
350
+ });
319
351
  if (process.env.DEBUG && result.details) {
320
352
  console.log(chalk.gray('📋 Full Result:'));
321
353
  console.log(chalk.gray(JSON.stringify(result, null, 2)));
@@ -1,14 +1,14 @@
1
1
  import chalk from 'chalk';
2
- import { ServiceOrchestrator } from "../../service-management/ServiceOrchestrator.js";
3
- import { StandardOptions } from '../shared/utils/cli-options.js';
4
- import { ConfigLoader } from '../shared/utils/config-loader.js';
2
+ import { ServiceOrchestrator } from '../service-management/ServiceOrchestrator.js';
3
+ import { StandardOptions } from '../lib/shared/utils/cli-options.js';
4
+ import { ConfigLoader } from '../lib/shared/utils/config-loader.js';
5
5
  export function registerDiagnoseCommand(program) {
6
6
  const command = program.command('diagnose [service-path]').description('Diagnose and report issues with an existing service').option('--deep-scan', 'Perform deep analysis including dependencies and deployment readiness').option('--export-report <file>', 'Export diagnostic report to file').option('--fix-suggestions', 'Include suggested fixes for issues');
7
7
 
8
8
  // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
9
9
  StandardOptions.define(command).action(async (servicePath, options) => {
10
10
  try {
11
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
11
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options);
12
12
  const configLoader = new ConfigLoader({
13
13
  verbose: options.verbose,
14
14
  quiet: options.quiet,
@@ -75,7 +75,7 @@ export function registerDiagnoseCommand(program) {
75
75
  process.exit(1);
76
76
  }
77
77
  } catch (error) {
78
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options || {});
78
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options || {});
79
79
  output.error(`Diagnosis failed: ${error.message}`);
80
80
  process.exit(1);
81
81
  }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Deployment UI Helpers
3
+ * Handles confirmation prompts and next steps display
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+
8
+ /**
9
+ * Prompt user for deployment confirmation
10
+ * @param {Object} options - CLI options
11
+ * @returns {Promise<boolean>} Whether user confirmed
12
+ */
13
+ export async function confirmDeployment(options) {
14
+ // Skip confirmation if: --yes flag, --dry-run mode, or non-interactive terminal
15
+ if (options.dryRun) {
16
+ return true; // Dry run doesn't need confirmation
17
+ }
18
+ if (options.yes) {
19
+ console.log(chalk.gray('\n⚡ Auto-confirming deployment (--yes flag)\n'));
20
+ return true;
21
+ }
22
+ if (!process.stdin.isTTY) {
23
+ console.log(chalk.yellow('\n⚠️ Non-interactive mode: proceeding without confirmation'));
24
+ console.log(chalk.gray('💡 Tip: Use --yes to suppress this warning\n'));
25
+ return true;
26
+ }
27
+
28
+ // Interactive confirmation
29
+ console.log(''); // Blank line for spacing
30
+
31
+ const {
32
+ createPromptModule
33
+ } = await import('inquirer');
34
+ const prompt = createPromptModule();
35
+ const {
36
+ confirmed
37
+ } = await prompt([{
38
+ type: 'confirm',
39
+ name: 'confirmed',
40
+ message: chalk.bold('Proceed with this deployment?'),
41
+ default: false
42
+ }]);
43
+ if (!confirmed) {
44
+ console.log(chalk.yellow('\n❌ Deployment cancelled by user\n'));
45
+ console.log(chalk.gray('💡 Tip: Use --dry-run to preview changes without deploying'));
46
+ return false;
47
+ }
48
+ console.log(''); // Blank line before starting deployment
49
+ return true;
50
+ }
51
+
52
+ /**
53
+ * Display deployment results summary
54
+ * @param {Object} resultData - Deployment result data
55
+ */
56
+ export function displayDeploymentResults(resultData) {
57
+ const {
58
+ result,
59
+ serviceName,
60
+ serviceType,
61
+ selectedDomain,
62
+ environment
63
+ } = resultData;
64
+ console.log(chalk.green('\n✅ Deployment Completed Successfully!\n'));
65
+ console.log(chalk.gray('─'.repeat(60)));
66
+
67
+ // Display results from orchestrator
68
+ if (result.url) {
69
+ console.log(chalk.white(`🌐 Service URL: ${chalk.bold(result.url)}`));
70
+ }
71
+ console.log(chalk.white(`📦 Service: ${serviceName}`));
72
+ console.log(chalk.white(`🔧 Type: ${serviceType}`));
73
+ console.log(chalk.white(`🌍 Domain: ${selectedDomain}`));
74
+ console.log(chalk.white(`🌎 Environment: ${environment || 'production'}`));
75
+ if (result.workerId) {
76
+ console.log(chalk.white(`👤 Worker ID: ${result.workerId}`));
77
+ }
78
+ if (result.deploymentId) {
79
+ console.log(chalk.white(`📋 Deployment ID: ${result.deploymentId}`));
80
+ }
81
+ if (result.status) {
82
+ const statusColor = result.status.toLowerCase().includes('success') ? chalk.green : chalk.yellow;
83
+ console.log(chalk.white(`📊 Status: ${statusColor(result.status)}`));
84
+ }
85
+
86
+ // Display audit information if available
87
+ if (result.auditLog) {
88
+ console.log(chalk.cyan('\n📋 Deployment Audit:'));
89
+ console.log(chalk.gray(` Started: ${result.auditLog.startTime}`));
90
+ console.log(chalk.gray(` Completed: ${result.auditLog.endTime}`));
91
+ console.log(chalk.gray(` Duration: ${result.auditLog.duration}ms`));
92
+ }
93
+ console.log(chalk.gray('─'.repeat(60)));
94
+ }
95
+
96
+ /**
97
+ * Display next steps after deployment
98
+ * @param {Object} stepsData - Next steps data
99
+ */
100
+ export function displayNextSteps(stepsData) {
101
+ const {
102
+ result,
103
+ selectedDomain,
104
+ serviceName,
105
+ dryRun
106
+ } = stepsData;
107
+ if (dryRun) {
108
+ console.log(chalk.cyan('\n💡 Dry Run Complete'));
109
+ console.log(chalk.white(` • Review the plan above`));
110
+ console.log(chalk.white(` • Remove --dry-run to execute deployment\n`));
111
+ return;
112
+ }
113
+ console.log(chalk.cyan('\n💡 Next Steps:\n'));
114
+
115
+ // Show both URLs if worker deployed
116
+ if (result.url) {
117
+ console.log(chalk.white(` 🌐 Your service is live at:`));
118
+ console.log(chalk.green(` ${result.url}`));
119
+
120
+ // Show custom domain if different from workers.dev
121
+ if (selectedDomain !== 'workers.cloudflare.com' && !selectedDomain.includes('workers.dev')) {
122
+ console.log(chalk.white(`\n ⚠️ Custom domain requires DNS setup:`));
123
+ console.log(chalk.yellow(` Domain: ${selectedDomain}`));
124
+ console.log(chalk.gray(` Add CNAME record: ${selectedDomain} → workers.dev`));
125
+ console.log(chalk.gray(` Or add route in Cloudflare Dashboard`));
126
+ }
127
+ }
128
+ console.log(chalk.white(`\n 📝 Testing:`));
129
+ console.log(chalk.gray(` curl ${result.url || `https://${selectedDomain}`}/health`));
130
+ console.log(chalk.white(`\n 📊 Monitoring:`));
131
+ console.log(chalk.gray(` wrangler tail ${serviceName}`));
132
+ console.log(chalk.gray(` https://dash.cloudflare.com`));
133
+ if (result.deploymentId) {
134
+ console.log(chalk.white(`\n 🔄 Rollback (if needed):`));
135
+ console.log(chalk.gray(` clodo-service rollback ${result.deploymentId}`));
136
+ }
137
+ console.log(''); // Blank line at end
138
+ }