@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,10 +0,0 @@
1
- import { Command } from 'commander';
2
- const program = new Command();
3
- program.name('clodo-service-test').description('Test Clodo Framework CLI').version('1.0.0');
4
- program.command('hello').description('Say hello').action(() => {
5
- console.log('Hello from Clodo Service CLI!');
6
- });
7
- program.command('create').description('Create a new service').action(() => {
8
- console.log('Create command would run here...');
9
- });
10
- program.parse();
@@ -1,91 +0,0 @@
1
- /**
2
- * Assess Command - Run intelligent capability assessment
3
- * Requires @tamyla/clodo-orchestration package for professional edition
4
- */
5
-
6
- import chalk from 'chalk';
7
- import { StandardOptions } from '../shared/utils/cli-options.js';
8
- import { ConfigLoader } from '../shared/utils/config-loader.js';
9
- export function registerAssessCommand(program) {
10
- const command = program.command('assess [service-path]').description('Run intelligent capability assessment (requires @tamyla/clodo-orchestration)').option('--export <file>', 'Export assessment results to JSON file').option('--domain <domain>', 'Domain name for assessment').option('--service-type <type>', 'Service type for assessment').option('--token <token>', 'Cloudflare API token');
11
-
12
- // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
13
- StandardOptions.define(command).action(async (servicePath, options) => {
14
- try {
15
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
16
- const configLoader = new ConfigLoader({
17
- verbose: options.verbose,
18
- quiet: options.quiet,
19
- json: options.json
20
- });
21
-
22
- // Load config from file if specified
23
- let configFileData = {};
24
- if (options.configFile) {
25
- configFileData = configLoader.loadSafe(options.configFile, {});
26
- if (options.verbose && !options.quiet) {
27
- output.info(`Loaded configuration from: ${options.configFile}`);
28
- }
29
- }
30
-
31
- // Substitute environment variables
32
- configFileData = configLoader.substituteEnvironmentVariables(configFileData);
33
-
34
- // Merge config file defaults with CLI options (CLI takes precedence)
35
- const mergedOptions = configLoader.merge(configFileData, options);
36
-
37
- // Try to load professional orchestration package
38
- let orchestrationModule;
39
- try {
40
- orchestrationModule = await import('@tamyla/clodo-orchestration');
41
- } catch (err) {
42
- output.error('❌ clodo-orchestration package not found');
43
- output.info('💡 Install with: npm install @tamyla/clodo-orchestration');
44
- process.exit(1);
45
- }
46
- const {
47
- CapabilityAssessmentEngine,
48
- ServiceAutoDiscovery,
49
- runAssessmentWorkflow
50
- } = orchestrationModule;
51
- const targetPath = servicePath || process.cwd();
52
- output.section('Professional Capability Assessment');
53
- output.list([`Service Path: ${targetPath}`, mergedOptions.domain ? `Domain: ${mergedOptions.domain}` : null, mergedOptions.serviceType ? `Service Type: ${mergedOptions.serviceType}` : null].filter(Boolean));
54
-
55
- // Use the assessment workflow
56
- const assessment = await runAssessmentWorkflow({
57
- servicePath: targetPath,
58
- domain: mergedOptions.domain,
59
- serviceType: mergedOptions.serviceType,
60
- token: mergedOptions.token || process.env.CLOUDFLARE_API_TOKEN
61
- });
62
-
63
- // Display results
64
- output.section('✅ Assessment Results');
65
- output.list([`Service Type: ${assessment.mergedInputs?.serviceType || assessment.serviceType || 'Not determined'}`, `Confidence: ${assessment.confidence}%`]);
66
- if (assessment.gapAnalysis?.missing) {
67
- if (assessment.gapAnalysis.missing.length > 0) {
68
- output.warning('⚠️ Missing Capabilities:');
69
- const missingItems = assessment.gapAnalysis.missing.map(gap => `${gap.capability}: ${gap.reason || 'Not available'}`);
70
- output.list(missingItems);
71
- }
72
- }
73
-
74
- // Export results if requested
75
- if (mergedOptions.export) {
76
- const {
77
- writeFileSync
78
- } = await import('fs');
79
- writeFileSync(mergedOptions.export, JSON.stringify(assessment, null, 2));
80
- output.success(`📄 Results exported to: ${mergedOptions.export}`);
81
- }
82
- } catch (error) {
83
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options || {});
84
- output.error(`Assessment failed: ${error.message}`);
85
- if (process.env.DEBUG) {
86
- output.debug(error.stack);
87
- }
88
- process.exit(1);
89
- }
90
- });
91
- }
@@ -1,77 +0,0 @@
1
- /**
2
- * Create Command - Create a new Clodo service with conversational setup
3
- *
4
- * Input Strategy: FULL three-tier collection (88 fields)
5
- * Uses ServiceOrchestrator to collect all required information interactively
6
- */
7
-
8
- import chalk from 'chalk';
9
- import { ServiceOrchestrator } from "../../service-management/ServiceOrchestrator.js";
10
- import { StandardOptions } from '../shared/utils/cli-options.js';
11
- import { ConfigLoader } from '../shared/utils/config-loader.js';
12
- export function registerCreateCommand(program) {
13
- const command = program.command('create').description('Create a new Clodo service with conversational setup').option('-n, --non-interactive', 'Run in non-interactive mode with all required parameters').option('--service-name <name>', 'Service name (required in non-interactive mode)').option('--service-type <type>', 'Service type: data-service, auth-service, content-service, api-gateway, generic', 'generic').option('--domain-name <domain>', 'Domain name (required in non-interactive mode)').option('--cloudflare-token <token>', 'Cloudflare API token (required in non-interactive mode)').option('--cloudflare-account-id <id>', 'Cloudflare account ID (required in non-interactive mode)').option('--cloudflare-zone-id <id>', 'Cloudflare zone ID (required in non-interactive mode)').option('--environment <env>', 'Target environment: development, staging, production', 'development').option('--output-path <path>', 'Output directory for generated service', '.').option('--template-path <path>', 'Path to service templates', './templates').option('--force', 'Skip confirmation prompts').option('--validate', 'Validate service after creation');
14
-
15
- // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
16
- StandardOptions.define(command).action(async options => {
17
- try {
18
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
19
- const configLoader = new ConfigLoader({
20
- verbose: options.verbose,
21
- quiet: options.quiet,
22
- json: options.json
23
- });
24
-
25
- // Load config from file if specified
26
- let configFileData = {};
27
- if (options.configFile) {
28
- configFileData = configLoader.loadSafe(options.configFile, {});
29
- if (options.verbose && !options.quiet) {
30
- output.info(`Loaded configuration from: ${options.configFile}`);
31
- }
32
- }
33
-
34
- // Merge config file defaults with CLI options (CLI takes precedence)
35
- const mergedOptions = configLoader.merge(configFileData, options);
36
- const orchestrator = new ServiceOrchestrator({
37
- interactive: !mergedOptions.nonInteractive,
38
- outputPath: mergedOptions.outputPath,
39
- templatePath: mergedOptions.templatePath
40
- });
41
- if (mergedOptions.nonInteractive) {
42
- // Validate required parameters for non-interactive mode
43
- const required = ['serviceName', 'domainName', 'cloudflareToken', 'cloudflareAccountId', 'cloudflareZoneId'];
44
- const missing = required.filter(key => !mergedOptions[key]);
45
- if (missing.length > 0) {
46
- output.error(`Missing required parameters: ${missing.join(', ')}`);
47
- output.info('Use --help for parameter details');
48
- process.exit(1);
49
- }
50
-
51
- // Convert merged options to core inputs
52
- const coreInputs = {
53
- serviceName: mergedOptions.serviceName,
54
- serviceType: mergedOptions.serviceType,
55
- domainName: mergedOptions.domainName,
56
- cloudflareToken: mergedOptions.cloudflareToken,
57
- cloudflareAccountId: mergedOptions.cloudflareAccountId,
58
- cloudflareZoneId: mergedOptions.cloudflareZoneId,
59
- environment: mergedOptions.environment
60
- };
61
- await orchestrator.runNonInteractive(coreInputs);
62
- } else {
63
- await orchestrator.runInteractive();
64
- }
65
- output.success('Service creation completed successfully!');
66
- output.section('Next steps');
67
- output.list(['cd into your new service directory', 'Run npm install', 'Configure additional settings in src/config/domains.js', 'Run npm run deploy to deploy to Cloudflare']);
68
- } catch (error) {
69
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options || {});
70
- output.error(`Service creation failed: ${error.message}`);
71
- if (error.details) {
72
- output.warning(`Details: ${error.details}`);
73
- }
74
- process.exit(1);
75
- }
76
- });
77
- }
@@ -1,83 +0,0 @@
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';
5
- export function registerDiagnoseCommand(program) {
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
-
8
- // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
9
- StandardOptions.define(command).action(async (servicePath, options) => {
10
- try {
11
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
12
- const configLoader = new ConfigLoader({
13
- verbose: options.verbose,
14
- quiet: options.quiet,
15
- json: options.json
16
- });
17
-
18
- // Load config from file if specified
19
- let configFileData = {};
20
- if (options.configFile) {
21
- configFileData = configLoader.loadSafe(options.configFile, {});
22
- if (options.verbose && !options.quiet) {
23
- output.info(`Loaded configuration from: ${options.configFile}`);
24
- }
25
- }
26
-
27
- // Merge config file defaults with CLI options (CLI takes precedence)
28
- const mergedOptions = configLoader.merge(configFileData, options);
29
- const orchestrator = new ServiceOrchestrator();
30
-
31
- // Auto-detect service path if not provided
32
- if (!servicePath) {
33
- servicePath = await orchestrator.detectServicePath();
34
- if (!servicePath) {
35
- output.error('No service path provided and could not auto-detect service directory');
36
- process.exit(1);
37
- }
38
- }
39
- output.info('🔍 Diagnosing service...');
40
- const diagnosis = await orchestrator.diagnoseService(servicePath, mergedOptions);
41
-
42
- // Display results
43
- output.section('Diagnostic Report');
44
- output.list([`Service: ${diagnosis.serviceName || 'Unknown'}`, `Path: ${servicePath}`]);
45
- if (diagnosis.errors.length > 0) {
46
- output.warning('❌ Critical Errors:');
47
- diagnosis.errors.forEach(error => {
48
- let msg = `• ${error.message}`;
49
- if (error.location) msg += ` (Location: ${error.location})`;
50
- if (error.suggestion) msg += ` 💡 ${error.suggestion}`;
51
- output.warning(msg);
52
- });
53
- }
54
- if (diagnosis.warnings.length > 0) {
55
- output.warning('⚠️ Warnings:');
56
- diagnosis.warnings.forEach(warning => {
57
- let msg = `• ${warning.message}`;
58
- if (warning.suggestion) msg += ` 💡 ${warning.suggestion}`;
59
- output.warning(msg);
60
- });
61
- }
62
- if (diagnosis.recommendations.length > 0) {
63
- output.info('💡 Recommendations:');
64
- output.list(diagnosis.recommendations);
65
- }
66
-
67
- // Export report if requested
68
- if (mergedOptions.exportReport) {
69
- await orchestrator.exportDiagnosticReport(diagnosis, mergedOptions.exportReport);
70
- output.success(`📄 Report exported to: ${mergedOptions.exportReport}`);
71
- }
72
-
73
- // Exit with error code if critical issues found
74
- if (diagnosis.errors.length > 0) {
75
- process.exit(1);
76
- }
77
- } catch (error) {
78
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options || {});
79
- output.error(`Diagnosis failed: ${error.message}`);
80
- process.exit(1);
81
- }
82
- });
83
- }
@@ -1,138 +0,0 @@
1
- /**
2
- * CLI Helpers - Shared utilities for all commands
3
- */
4
-
5
- import chalk from 'chalk';
6
- import { existsSync, readFileSync } from 'fs';
7
- import { join, resolve } from 'path';
8
-
9
- /**
10
- * Load JSON configuration file
11
- */
12
- export function loadJsonConfig(configPath) {
13
- try {
14
- const fullPath = resolve(configPath);
15
- if (!existsSync(fullPath)) {
16
- throw new Error(`Configuration file not found: ${fullPath}`);
17
- }
18
- const content = readFileSync(fullPath, 'utf8');
19
- const config = JSON.parse(content);
20
-
21
- // Validate required fields
22
- const required = ['customer', 'environment', 'domainName', 'cloudflareToken'];
23
- const missing = required.filter(field => !config[field]);
24
- if (missing.length > 0) {
25
- throw new Error(`Missing required configuration fields: ${missing.join(', ')}`);
26
- }
27
- console.log(chalk.green(`✅ Loaded configuration from: ${fullPath}`));
28
- return config;
29
- } catch (error) {
30
- if (error instanceof SyntaxError) {
31
- throw new Error(`Invalid JSON in configuration file: ${error.message}`);
32
- }
33
- throw error;
34
- }
35
- }
36
-
37
- /**
38
- * Show progress indicator for deployment steps
39
- */
40
- export function showProgress(message, duration = 2000) {
41
- return new Promise(resolve => {
42
- process.stdout.write(chalk.cyan(`⏳ ${message}...`));
43
- const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
44
- let i = 0;
45
- const interval = setInterval(() => {
46
- process.stdout.write(`\r${chalk.cyan(spinner[i])} ${message}...`);
47
- i = (i + 1) % spinner.length;
48
- }, 100);
49
- setTimeout(() => {
50
- clearInterval(interval);
51
- process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
52
- resolve();
53
- }, duration);
54
- });
55
- }
56
-
57
- /**
58
- * Early validation function to check prerequisites before deployment
59
- */
60
- export async function validateDeploymentPrerequisites(coreInputs, options) {
61
- const issues = [];
62
- console.log(chalk.cyan('\n🔍 Pre-deployment Validation'));
63
- console.log(chalk.gray('─'.repeat(40)));
64
-
65
- // Check required fields
66
- if (!coreInputs.customer) {
67
- issues.push('Customer name is required');
68
- }
69
- if (!coreInputs.environment) {
70
- issues.push('Environment is required');
71
- }
72
- if (!coreInputs.domainName) {
73
- issues.push('Domain name is required');
74
- }
75
- if (!coreInputs.cloudflareToken) {
76
- issues.push('Cloudflare API token is required');
77
- }
78
-
79
- // Check Cloudflare token format (basic validation)
80
- if (coreInputs.cloudflareToken && !coreInputs.cloudflareToken.startsWith('CLOUDFLARE_API_TOKEN=')) {
81
- if (coreInputs.cloudflareToken.length < 40) {
82
- issues.push('Cloudflare API token appears to be invalid (too short)');
83
- }
84
- }
85
-
86
- // Check if service path exists
87
- if (options.servicePath && options.servicePath !== '.') {
88
- if (!existsSync(options.servicePath)) {
89
- issues.push(`Service path does not exist: ${options.servicePath}`);
90
- }
91
- }
92
-
93
- // Check for wrangler.toml if not dry run
94
- if (!options.dryRun) {
95
- const wranglerPath = join(options.servicePath || '.', 'wrangler.toml');
96
- if (!existsSync(wranglerPath)) {
97
- issues.push('wrangler.toml not found in service directory');
98
- }
99
- }
100
-
101
- // Report issues
102
- if (issues.length > 0) {
103
- console.log(chalk.red('\n❌ Validation Failed:'));
104
- issues.forEach(issue => {
105
- console.log(chalk.red(` • ${issue}`));
106
- });
107
- console.log(chalk.gray('\n─'.repeat(40)));
108
- return false;
109
- }
110
- console.log(chalk.green('✅ All prerequisites validated'));
111
- console.log(chalk.gray('─'.repeat(40)));
112
- return true;
113
- }
114
-
115
- /**
116
- * Redact sensitive information from logs
117
- */
118
- export function redactSensitiveInfo(text) {
119
- if (typeof text !== 'string') return text;
120
-
121
- // Patterns to redact
122
- const patterns = [
123
- // Cloudflare API tokens
124
- [/(CLOUDFLARE_API_TOKEN=?)(\w{20,})/gi, '$1[REDACTED]'],
125
- // Generic API tokens/keys
126
- [/(api[_-]?token|api[_-]?key|auth[_-]?token)["']?[:=]\s*["']?([a-zA-Z0-9_-]{20,})["']?/gi, '$1: [REDACTED]'],
127
- // Passwords
128
- [/(password|passwd|pwd)["']?[:=]\s*["']?([^"'\s]{3,})["']?/gi, '$1: [REDACTED]'],
129
- // Secrets
130
- [/(secret|key)["']?[:=]\s*["']?([a-zA-Z0-9_-]{10,})["']?/gi, '$1: [REDACTED]'],
131
- // Account IDs (partial redaction)
132
- [/(account[_-]?id|zone[_-]?id)["']?[:=]\s*["']?([a-zA-Z0-9]{8})([a-zA-Z0-9]{24,})["']?/gi, '$1: $2[REDACTED]']];
133
- let redacted = text;
134
- patterns.forEach(([pattern, replacement]) => {
135
- redacted = redacted.replace(pattern, replacement);
136
- });
137
- return redacted;
138
- }
@@ -1,75 +0,0 @@
1
- /**
2
- * Update Command - Update an existing service configuration
3
- */
4
-
5
- import chalk from 'chalk';
6
- import { ServiceOrchestrator } from "../../service-management/ServiceOrchestrator.js";
7
- import { StandardOptions } from '../shared/utils/cli-options.js';
8
- import { ConfigLoader } from '../shared/utils/config-loader.js';
9
- export function registerUpdateCommand(program) {
10
- const command = program.command('update [service-path]').description('Update an existing service configuration').option('-i, --interactive', 'Run in interactive mode to select what to update').option('--domain-name <domain>', 'Update domain name').option('--cloudflare-token <token>', 'Update Cloudflare API token').option('--cloudflare-account-id <id>', 'Update Cloudflare account ID').option('--cloudflare-zone-id <id>', 'Update Cloudflare zone ID').option('--environment <env>', 'Update target environment: development, staging, production').option('--add-feature <feature>', 'Add a feature flag').option('--remove-feature <feature>', 'Remove a feature flag').option('--regenerate-configs', 'Regenerate all configuration files').option('--fix-errors', 'Attempt to fix common configuration errors').option('--preview', 'Show what would be changed without applying').option('--force', 'Skip confirmation prompts');
11
-
12
- // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
13
- StandardOptions.define(command).action(async (servicePath, options) => {
14
- try {
15
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options);
16
- const configLoader = new ConfigLoader({
17
- verbose: options.verbose,
18
- quiet: options.quiet,
19
- json: options.json
20
- });
21
-
22
- // Load config from file if specified
23
- let configFileData = {};
24
- if (options.configFile) {
25
- configFileData = configLoader.loadSafe(options.configFile, {});
26
- if (options.verbose && !options.quiet) {
27
- output.info(`Loaded configuration from: ${options.configFile}`);
28
- }
29
- }
30
-
31
- // Merge config file defaults with CLI options (CLI takes precedence)
32
- const mergedOptions = configLoader.merge(configFileData, options);
33
- const orchestrator = new ServiceOrchestrator();
34
-
35
- // Auto-detect service path if not provided
36
- if (!servicePath) {
37
- servicePath = await orchestrator.detectServicePath();
38
- if (!servicePath) {
39
- output.error('No service path provided and could not auto-detect service directory');
40
- output.info('Please run this command from within a service directory or specify the path');
41
- process.exit(1);
42
- }
43
- output.info(`Auto-detected service at: ${servicePath}`);
44
- }
45
-
46
- // Validate it's a service directory
47
- const isValid = await orchestrator.validateService(servicePath);
48
- if (!isValid.valid) {
49
- output.warning('Service has configuration issues. Use --fix-errors to attempt automatic fixes.');
50
- if (!mergedOptions.fixErrors) {
51
- output.info('Issues found:');
52
- output.list(isValid.issues || []);
53
- process.exit(1);
54
- }
55
- }
56
- if (mergedOptions.interactive) {
57
- await orchestrator.runInteractiveUpdate(servicePath);
58
- } else {
59
- await orchestrator.runNonInteractiveUpdate(servicePath, mergedOptions);
60
- }
61
- output.success('Service update completed successfully!');
62
- } catch (error) {
63
- const output = new (await import('../shared/utils/output-formatter.js')).OutputFormatter(options || {});
64
- output.error(`Service update failed: ${error.message}`);
65
- if (error.details) {
66
- output.warning(`Details: ${error.details}`);
67
- }
68
- if (error.recovery) {
69
- output.info('Recovery suggestions:');
70
- output.list(error.recovery);
71
- }
72
- process.exit(1);
73
- }
74
- });
75
- }