@tamyla/clodo-framework 3.1.22 → 3.1.24

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 (210) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +230 -1
  3. package/dist/cli/commands/assess.js +192 -0
  4. package/dist/cli/commands/create.js +77 -0
  5. package/dist/{bin → cli}/commands/deploy.js +36 -14
  6. package/dist/cli/commands/diagnose.js +83 -0
  7. package/dist/{bin → cli}/commands/helpers/deployment-verification.js +2 -3
  8. package/dist/{bin → cli}/commands/helpers/error-recovery.js +1 -1
  9. package/dist/{bin → cli}/commands/helpers/resource-detection.js +1 -1
  10. package/dist/cli/commands/helpers.js +110 -0
  11. package/dist/cli/commands/init-config.js +57 -0
  12. package/dist/cli/commands/update.js +102 -0
  13. package/dist/cli/commands/validate.js +65 -0
  14. package/dist/cli/security-cli.js +118 -0
  15. package/dist/config/FeatureManager.js +6 -0
  16. package/dist/config/clodo-create.example.json +26 -0
  17. package/dist/config/clodo-deploy.example.json +41 -0
  18. package/dist/config/clodo-update.example.json +46 -0
  19. package/dist/config/clodo-validate.example.json +41 -0
  20. package/dist/config/customers/template/development.env.template +37 -0
  21. package/dist/config/customers/template/production.env.template +39 -0
  22. package/dist/config/customers/template/staging.env.template +37 -0
  23. package/dist/config/customers.js +625 -0
  24. package/dist/config/domain-examples/README.md +464 -0
  25. package/dist/config/domain-examples/environment-mapped.json +168 -0
  26. package/dist/config/domain-examples/multi-domain.json +144 -0
  27. package/dist/config/domain-examples/single-domain.json +50 -0
  28. package/dist/config/domains.js +186 -0
  29. package/dist/config/examples +12 -0
  30. package/dist/config/features.js +61 -0
  31. package/dist/config/index.js +6 -0
  32. package/dist/config/staging-deployment.json +60 -0
  33. package/dist/config/validation-config.json +347 -0
  34. package/dist/database/database-orchestrator.js +795 -0
  35. package/dist/database/index.js +4 -0
  36. package/dist/deployment/index.js +11 -0
  37. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  38. package/dist/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  39. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  40. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  41. package/dist/deployment/orchestration/index.js +17 -0
  42. package/dist/deployment/rollback-manager.js +36 -0
  43. package/dist/deployment/wrangler-deployer.js +640 -0
  44. package/dist/handlers/GenericRouteHandler.js +532 -0
  45. package/dist/lib/database/deployment-db-manager.js +423 -0
  46. package/dist/lib/database/wrangler-d1-manager.js +685 -0
  47. package/dist/lib/deployment/modules/DeploymentConfiguration.js +395 -0
  48. package/dist/lib/deployment/modules/DeploymentOrchestrator.js +492 -0
  49. package/dist/lib/deployment/modules/EnvironmentManager.js +517 -0
  50. package/dist/lib/deployment/modules/MonitoringIntegration.js +560 -0
  51. package/dist/lib/deployment/modules/ValidationManager.js +342 -0
  52. package/dist/lib/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  53. package/dist/lib/deployment/orchestration/EnterpriseOrchestrator.js +21 -0
  54. package/dist/lib/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  55. package/dist/lib/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  56. package/dist/lib/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  57. package/dist/{bin → lib}/shared/cloudflare/domain-discovery.js +1 -1
  58. package/dist/{bin → lib}/shared/cloudflare/domain-manager.js +1 -1
  59. package/dist/{bin → lib}/shared/cloudflare/ops.js +4 -4
  60. package/dist/{bin → lib}/shared/config/command-config-manager.js +1 -1
  61. package/dist/{bin → lib}/shared/config/index.js +1 -1
  62. package/dist/{bin → lib}/shared/config/manifest-loader.js +3 -3
  63. package/dist/{bin → lib}/shared/deployment/credential-collector.js +1 -1
  64. package/dist/lib/shared/deployment/index.js +10 -0
  65. package/dist/{bin → lib}/shared/deployment/rollback-manager.js +1 -1
  66. package/dist/{bin → lib}/shared/deployment/utilities/d1-error-recovery.js +1 -1
  67. package/dist/{bin → lib}/shared/deployment/validator.js +1 -1
  68. package/dist/{bin → lib}/shared/deployment/workflows/interactive-database-workflow.js +1 -1
  69. package/dist/{bin → lib}/shared/monitoring/health-checker.js +2 -2
  70. package/dist/{bin → lib}/shared/routing/domain-router.js +1 -1
  71. package/dist/{bin → lib}/shared/utils/config-loader.js +47 -11
  72. package/dist/lib/shared/utils/service-config-manager.js +227 -0
  73. package/dist/{bin → lib}/shared/validation/ValidationRegistry.js +1 -1
  74. package/dist/migration/MigrationAdapters.js +608 -0
  75. package/dist/modules/ModuleManager.js +668 -0
  76. package/dist/modules/security.js +96 -0
  77. package/dist/orchestration/cross-domain-coordinator.js +1083 -0
  78. package/dist/orchestration/index.js +5 -0
  79. package/dist/orchestration/modules/DeploymentCoordinator.js +368 -0
  80. package/dist/orchestration/modules/DomainResolver.js +198 -0
  81. package/dist/orchestration/modules/StateManager.js +332 -0
  82. package/dist/orchestration/multi-domain-orchestrator.js +765 -0
  83. package/dist/routing/EnhancedRouter.js +158 -0
  84. package/dist/schema/SchemaManager.js +778 -0
  85. package/dist/security/index.js +2 -2
  86. package/dist/service-management/ConfirmationEngine.js +412 -0
  87. package/dist/service-management/ErrorTracker.js +299 -0
  88. package/dist/service-management/GenerationEngine.js +447 -0
  89. package/dist/service-management/InputCollector.js +619 -0
  90. package/dist/service-management/ServiceCreator.js +21 -0
  91. package/dist/service-management/ServiceOrchestrator.js +672 -0
  92. package/dist/service-management/generators/BaseGenerator.js +233 -0
  93. package/dist/service-management/generators/GeneratorRegistry.js +254 -0
  94. package/dist/service-management/generators/cicd/CiWorkflowGenerator.js +87 -0
  95. package/dist/service-management/generators/cicd/DeployWorkflowGenerator.js +106 -0
  96. package/dist/service-management/generators/code/ServiceHandlersGenerator.js +235 -0
  97. package/dist/service-management/generators/code/ServiceMiddlewareGenerator.js +116 -0
  98. package/dist/service-management/generators/code/ServiceUtilsGenerator.js +246 -0
  99. package/dist/service-management/generators/code/WorkerIndexGenerator.js +143 -0
  100. package/dist/service-management/generators/config/DevelopmentEnvGenerator.js +101 -0
  101. package/dist/service-management/generators/config/DomainsConfigGenerator.js +175 -0
  102. package/dist/service-management/generators/config/EnvExampleGenerator.js +178 -0
  103. package/dist/service-management/generators/config/ProductionEnvGenerator.js +97 -0
  104. package/dist/service-management/generators/config/StagingEnvGenerator.js +97 -0
  105. package/dist/service-management/generators/config/WranglerTomlGenerator.js +238 -0
  106. package/dist/service-management/generators/core/PackageJsonGenerator.js +243 -0
  107. package/dist/service-management/generators/core/SiteConfigGenerator.js +115 -0
  108. package/dist/service-management/generators/documentation/ApiDocsGenerator.js +331 -0
  109. package/dist/service-management/generators/documentation/ConfigurationDocsGenerator.js +294 -0
  110. package/dist/service-management/generators/documentation/DeploymentDocsGenerator.js +244 -0
  111. package/dist/service-management/generators/documentation/ReadmeGenerator.js +196 -0
  112. package/dist/service-management/generators/schemas/ServiceSchemaGenerator.js +190 -0
  113. package/dist/service-management/generators/scripts/DeployScriptGenerator.js +123 -0
  114. package/dist/service-management/generators/scripts/HealthCheckScriptGenerator.js +101 -0
  115. package/dist/service-management/generators/scripts/SetupScriptGenerator.js +88 -0
  116. package/dist/service-management/generators/service-types/StaticSiteGenerator.js +342 -0
  117. package/dist/service-management/generators/testing/EslintConfigGenerator.js +85 -0
  118. package/dist/service-management/generators/testing/IntegrationTestsGenerator.js +237 -0
  119. package/dist/service-management/generators/testing/JestConfigGenerator.js +72 -0
  120. package/dist/service-management/generators/testing/UnitTestsGenerator.js +277 -0
  121. package/dist/service-management/generators/tooling/DockerComposeGenerator.js +71 -0
  122. package/dist/service-management/generators/tooling/GitignoreGenerator.js +143 -0
  123. package/dist/service-management/generators/utils/FileWriter.js +179 -0
  124. package/dist/service-management/generators/utils/PathResolver.js +157 -0
  125. package/dist/service-management/generators/utils/ServiceManifestGenerator.js +111 -0
  126. package/dist/service-management/generators/utils/TemplateEngine.js +185 -0
  127. package/dist/service-management/generators/utils/index.js +18 -0
  128. package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
  129. package/dist/service-management/handlers/GenerationHandler.js +80 -0
  130. package/dist/service-management/handlers/InputHandler.js +59 -0
  131. package/dist/service-management/handlers/ValidationHandler.js +216 -0
  132. package/dist/service-management/index.js +14 -0
  133. package/dist/service-management/routing/DomainRouteMapper.js +311 -0
  134. package/dist/service-management/routing/RouteGenerator.js +266 -0
  135. package/dist/service-management/routing/WranglerRoutesBuilder.js +273 -0
  136. package/dist/service-management/routing/index.js +14 -0
  137. package/dist/service-management/services/DirectoryStructureService.js +56 -0
  138. package/dist/service-management/services/GenerationCoordinator.js +208 -0
  139. package/dist/service-management/services/GeneratorRegistry.js +174 -0
  140. package/dist/services/GenericDataService.js +501 -0
  141. package/dist/ui-structures/concepts/second-order-acquisition-strategy.md +286 -0
  142. package/dist/ui-structures/concepts/service-lifecycle-management.md +150 -0
  143. package/dist/ui-structures/concepts/service-manifest-guide.md +309 -0
  144. package/dist/ui-structures/concepts/three-tier-categorization-strategy.md +231 -0
  145. package/dist/ui-structures/creation/automated-generation-ui.json +246 -0
  146. package/dist/ui-structures/creation/core-inputs-ui.json +217 -0
  147. package/dist/ui-structures/creation/smart-confirmable-ui.json +451 -0
  148. package/dist/ui-structures/reference/absolutely-required-inputs.json +315 -0
  149. package/dist/ui-structures/reference/service-manifest-template.json +342 -0
  150. package/dist/utils/cloudflare/ops.js +1 -1
  151. package/dist/utils/file-manager.js +1 -1
  152. package/dist/utils/formatters.js +1 -1
  153. package/dist/utils/logger.js +1 -1
  154. package/dist/version/VersionDetector.js +813 -0
  155. package/dist/worker/index.js +4 -0
  156. package/dist/worker/integration.js +351 -0
  157. package/package.json +7 -15
  158. package/dist/bin/commands/validate.js +0 -51
  159. package/dist/bin/security/security-cli.js +0 -108
  160. package/dist/bin/shared/deployment/index.js +0 -10
  161. /package/dist/{bin → cli}/clodo-service.js +0 -0
  162. /package/dist/{bin → cli}/commands/helpers/deployment-ui.js +0 -0
  163. /package/dist/{bin → lib}/shared/cache/configuration-cache.js +0 -0
  164. /package/dist/{bin → lib}/shared/cloudflare/index.js +0 -0
  165. /package/dist/{bin → lib}/shared/config/ConfigurationManager.js +0 -0
  166. /package/dist/{bin → lib}/shared/config/cache.js +0 -0
  167. /package/dist/{bin → lib}/shared/config/cloudflare-service-validator.js +0 -0
  168. /package/dist/{bin → lib}/shared/config/manager.js +0 -0
  169. /package/dist/{bin → lib}/shared/database/connection-manager.js +0 -0
  170. /package/dist/{bin → lib}/shared/database/index.js +0 -0
  171. /package/dist/{bin → lib}/shared/database/orchestrator.js +0 -0
  172. /package/dist/{bin → lib}/shared/deployment/auditor.js +0 -0
  173. /package/dist/{bin → lib}/shared/deployment/workflows/deployment-summary.js +0 -0
  174. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-confirmation.js +0 -0
  175. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-domain-info-gatherer.js +0 -0
  176. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-secret-workflow.js +0 -0
  177. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-testing-workflow.js +0 -0
  178. /package/dist/{bin → lib}/shared/deployment/workflows/interactive-validation.js +0 -0
  179. /package/dist/{bin → lib}/shared/error-handling/error-classifier.js +0 -0
  180. /package/dist/{bin → lib}/shared/index.js +0 -0
  181. /package/dist/{bin → lib}/shared/logging/Logger.js +0 -0
  182. /package/dist/{bin → lib}/shared/monitoring/index.js +0 -0
  183. /package/dist/{bin → lib}/shared/monitoring/memory-manager.js +0 -0
  184. /package/dist/{bin → lib}/shared/monitoring/production-monitor.js +0 -0
  185. /package/dist/{bin → lib}/shared/production-tester/api-tester.js +0 -0
  186. /package/dist/{bin → lib}/shared/production-tester/auth-tester.js +0 -0
  187. /package/dist/{bin → lib}/shared/production-tester/core.js +0 -0
  188. /package/dist/{bin → lib}/shared/production-tester/database-tester.js +0 -0
  189. /package/dist/{bin → lib}/shared/production-tester/index.js +0 -0
  190. /package/dist/{bin → lib}/shared/production-tester/load-tester.js +0 -0
  191. /package/dist/{bin → lib}/shared/production-tester/performance-tester.js +0 -0
  192. /package/dist/{bin → lib}/shared/security/api-token-manager.js +0 -0
  193. /package/dist/{bin → lib}/shared/security/index.js +0 -0
  194. /package/dist/{bin → lib}/shared/security/secret-generator.js +0 -0
  195. /package/dist/{bin → lib}/shared/security/secure-token-manager.js +0 -0
  196. /package/dist/{bin → lib}/shared/utils/ErrorHandler.js +0 -0
  197. /package/dist/{bin → lib}/shared/utils/cli-options.js +0 -0
  198. /package/dist/{bin → lib}/shared/utils/deployment-validator.js +0 -0
  199. /package/dist/{bin → lib}/shared/utils/error-recovery.js +0 -0
  200. /package/dist/{bin → lib}/shared/utils/file-manager.js +0 -0
  201. /package/dist/{bin → lib}/shared/utils/formatters.js +0 -0
  202. /package/dist/{bin → lib}/shared/utils/graceful-shutdown-manager.js +0 -0
  203. /package/dist/{bin → lib}/shared/utils/index.js +0 -0
  204. /package/dist/{bin → lib}/shared/utils/interactive-prompts.js +0 -0
  205. /package/dist/{bin → lib}/shared/utils/interactive-utils.js +0 -0
  206. /package/dist/{bin → lib}/shared/utils/output-formatter.js +0 -0
  207. /package/dist/{bin → lib}/shared/utils/progress-manager.js +0 -0
  208. /package/dist/{bin → lib}/shared/utils/progress-spinner.js +0 -0
  209. /package/dist/{bin → lib}/shared/utils/rate-limiter.js +0 -0
  210. /package/dist/{bin → lib}/shared/utils/sensitive-redactor.js +0 -0
@@ -0,0 +1,83 @@
1
+ import chalk from 'chalk';
2
+ import path from 'path';
3
+ import { ServiceOrchestrator } from '../service-management/ServiceOrchestrator.js';
4
+ import { StandardOptions } from '../lib/shared/utils/cli-options.js';
5
+ import { ServiceConfigManager } from '../lib/shared/utils/service-config-manager.js';
6
+ export function registerDiagnoseCommand(program) {
7
+ 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').option('--show-config-sources', 'Display all configuration sources and merged result');
8
+
9
+ // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
10
+ StandardOptions.define(command).action(async (servicePath, options) => {
11
+ try {
12
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options);
13
+ const configManager = new ServiceConfigManager({
14
+ verbose: options.verbose,
15
+ quiet: options.quiet,
16
+ json: options.json,
17
+ showSources: options.showConfigSources
18
+ });
19
+ const orchestrator = new ServiceOrchestrator();
20
+
21
+ // Validate service path with better error handling
22
+ try {
23
+ servicePath = await configManager.validateServicePath(servicePath, orchestrator);
24
+ } catch (error) {
25
+ output.error(error.message);
26
+ if (error.suggestions) {
27
+ output.info('Suggestions:');
28
+ output.list(error.suggestions);
29
+ }
30
+ process.exit(1);
31
+ }
32
+
33
+ // Load and merge all configurations
34
+ const mergedOptions = await configManager.loadServiceConfig(servicePath, options, {
35
+ deepScan: false,
36
+ exportReport: null,
37
+ fixSuggestions: false
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('../lib/shared/utils/output-formatter.js')).OutputFormatter(options || {});
79
+ output.error(`Diagnosis failed: ${error.message}`);
80
+ process.exit(1);
81
+ }
82
+ });
83
+ }
@@ -3,8 +3,7 @@
3
3
  * Provides UI-specific deployment verification by delegating to shared infrastructure
4
4
  */
5
5
 
6
- import { verifyWorkerDeployment, healthCheckWithBackoff } from '../../shared/monitoring/health-checker.js';
7
- import { checkHealth } from '../../shared/monitoring/health-checker.js';
6
+ import { verifyWorkerDeployment, healthCheckWithBackoff, checkHealth } from '../../lib/shared/monitoring/health-checker.js';
8
7
  import chalk from 'chalk';
9
8
  import readline from 'readline';
10
9
 
@@ -158,7 +157,7 @@ async function discoverUrlFromCloudflare(cloudflareSettings, options = {}) {
158
157
  try {
159
158
  const {
160
159
  CloudflareAPI
161
- } = await import('../../../utils/cloudflare/api.js');
160
+ } = await import('../../utils/cloudflare/api.js');
162
161
  const api = new CloudflareAPI(cloudflareSettings.token);
163
162
 
164
163
  // Get worker routes for the zone
@@ -3,7 +3,7 @@
3
3
  * Provides interactive error recovery by delegating to shared error classification
4
4
  */
5
5
 
6
- import { classifyError, getRecoverySuggestions } from '../../shared/error-handling/error-classifier.js';
6
+ import { classifyError, getRecoverySuggestions } from '../../lib/shared/error-handling/error-classifier.js';
7
7
  import chalk from 'chalk';
8
8
  import readline from 'readline';
9
9
 
@@ -22,7 +22,7 @@ export async function detectExistingResources(serviceName, manifest, credentials
22
22
  // Import CloudflareAPI to check existing resources
23
23
  const {
24
24
  CloudflareAPI
25
- } = await import('../../../utils/cloudflare/api.js');
25
+ } = await import('../../utils/cloudflare/api.js');
26
26
  const cfApi = new CloudflareAPI(credentials.token);
27
27
 
28
28
  // Check if worker already exists
@@ -0,0 +1,110 @@
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
+ * Show progress indicator for deployment steps
11
+ */
12
+ export function showProgress(message, duration = 2000) {
13
+ return new Promise(resolve => {
14
+ process.stdout.write(chalk.cyan(`⏳ ${message}...`));
15
+ const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
16
+ let i = 0;
17
+ const interval = setInterval(() => {
18
+ process.stdout.write(`\r${chalk.cyan(spinner[i])} ${message}...`);
19
+ i = (i + 1) % spinner.length;
20
+ }, 100);
21
+ setTimeout(() => {
22
+ clearInterval(interval);
23
+ process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
24
+ resolve();
25
+ }, duration);
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Early validation function to check prerequisites before deployment
31
+ */
32
+ export async function validateDeploymentPrerequisites(coreInputs, options) {
33
+ const issues = [];
34
+ console.log(chalk.cyan('\n🔍 Pre-deployment Validation'));
35
+ console.log(chalk.gray('─'.repeat(40)));
36
+
37
+ // Check required fields
38
+ if (!coreInputs.customer) {
39
+ issues.push('Customer name is required');
40
+ }
41
+ if (!coreInputs.environment) {
42
+ issues.push('Environment is required');
43
+ }
44
+ if (!coreInputs.domainName) {
45
+ issues.push('Domain name is required');
46
+ }
47
+ if (!coreInputs.cloudflareToken) {
48
+ issues.push('Cloudflare API token is required');
49
+ }
50
+
51
+ // Check Cloudflare token format (basic validation)
52
+ if (coreInputs.cloudflareToken && !coreInputs.cloudflareToken.startsWith('CLOUDFLARE_API_TOKEN=')) {
53
+ if (coreInputs.cloudflareToken.length < 40) {
54
+ issues.push('Cloudflare API token appears to be invalid (too short)');
55
+ }
56
+ }
57
+
58
+ // Check if service path exists
59
+ if (options.servicePath && options.servicePath !== '.') {
60
+ if (!existsSync(options.servicePath)) {
61
+ issues.push(`Service path does not exist: ${options.servicePath}`);
62
+ }
63
+ }
64
+
65
+ // Check for wrangler.toml if not dry run
66
+ if (!options.dryRun) {
67
+ const wranglerPath = join(options.servicePath || '.', 'wrangler.toml');
68
+ if (!existsSync(wranglerPath)) {
69
+ issues.push('wrangler.toml not found in service directory');
70
+ }
71
+ }
72
+
73
+ // Report issues
74
+ if (issues.length > 0) {
75
+ console.log(chalk.red('\n❌ Validation Failed:'));
76
+ issues.forEach(issue => {
77
+ console.log(chalk.red(` • ${issue}`));
78
+ });
79
+ console.log(chalk.gray('\n─'.repeat(40)));
80
+ return false;
81
+ }
82
+ console.log(chalk.green('✅ All prerequisites validated'));
83
+ console.log(chalk.gray('─'.repeat(40)));
84
+ return true;
85
+ }
86
+
87
+ /**
88
+ * Redact sensitive information from logs
89
+ */
90
+ export function redactSensitiveInfo(text) {
91
+ if (typeof text !== 'string') return text;
92
+
93
+ // Patterns to redact
94
+ const patterns = [
95
+ // Cloudflare API tokens
96
+ [/(CLOUDFLARE_API_TOKEN=?)(\w{20,})/gi, '$1[REDACTED]'],
97
+ // Generic API tokens/keys
98
+ [/(api[_-]?token|api[_-]?key|auth[_-]?token)["']?[:=]\s*["']?([a-zA-Z0-9_-]{20,})["']?/gi, '$1: [REDACTED]'],
99
+ // Passwords
100
+ [/(password|passwd|pwd)["']?[:=]\s*["']?([^"'\s]{3,})["']?/gi, '$1: [REDACTED]'],
101
+ // Secrets
102
+ [/(secret|key)["']?[:=]\s*["']?([a-zA-Z0-9_-]{10,})["']?/gi, '$1: [REDACTED]'],
103
+ // Account IDs (partial redaction)
104
+ [/(account[_-]?id|zone[_-]?id)["']?[:=]\s*["']?([a-zA-Z0-9]{8})([a-zA-Z0-9]{24,})["']?/gi, '$1: $2[REDACTED]']];
105
+ let redacted = text;
106
+ patterns.forEach(([pattern, replacement]) => {
107
+ redacted = redacted.replace(pattern, replacement);
108
+ });
109
+ return redacted;
110
+ }
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Initialize Configuration Command
5
+ * Copies the framework's validation-config.json to the service directory for customization
6
+ */
7
+ import { copyFile, access } from 'fs/promises';
8
+ import { join, dirname } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ import chalk from 'chalk';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+
14
+ // Path to framework's bundled config
15
+ const FRAMEWORK_CONFIG_PATH = join(__dirname, '../config/validation-config.json');
16
+
17
+ /**
18
+ * Register the init-config command with the CLI
19
+ */
20
+ export function registerInitConfigCommand(program) {
21
+ program.command('init-config').description('Initialize validation-config.json in your service directory').option('-f, --force', 'Overwrite existing validation-config.json', false).action(handler);
22
+ }
23
+ async function handler(options) {
24
+ const targetPath = join(process.cwd(), 'validation-config.json');
25
+ try {
26
+ // Check if file already exists
27
+ try {
28
+ await access(targetPath);
29
+ if (!options.force) {
30
+ console.log(chalk.yellow('⚠️ validation-config.json already exists.'));
31
+ console.log(chalk.gray(' Use --force to overwrite.'));
32
+ process.exit(0);
33
+ } else {
34
+ console.log(chalk.yellow('🔄 Overwriting existing validation-config.json...'));
35
+ }
36
+ } catch {
37
+ // File doesn't exist, proceed
38
+ }
39
+
40
+ // Copy framework config to service directory
41
+ await copyFile(FRAMEWORK_CONFIG_PATH, targetPath);
42
+ console.log(chalk.green('✅ Successfully initialized validation-config.json'));
43
+ console.log(chalk.gray('\n📝 Configuration file details:'));
44
+ console.log(chalk.gray(` Location: ${targetPath}`));
45
+ console.log(chalk.gray('\n💡 Usage:'));
46
+ console.log(chalk.gray(' • Customize timing values (timeouts, intervals)'));
47
+ console.log(chalk.gray(' • Add service-specific endpoints for validation'));
48
+ console.log(chalk.gray(' • Configure platform-specific commands'));
49
+ console.log(chalk.gray(' • Set environment-specific requirements'));
50
+ console.log(chalk.gray('\n⚠️ Note: Most services don\'t need this file.'));
51
+ console.log(chalk.gray(' The framework provides sensible defaults.'));
52
+ } catch (error) {
53
+ console.error(chalk.red('❌ Failed to initialize configuration:'));
54
+ console.error(chalk.red(` ${error.message}`));
55
+ process.exit(1);
56
+ }
57
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Update Command - Update an existing service configuration
3
+ */
4
+
5
+ import chalk from 'chalk';
6
+ import path from 'path';
7
+ import { ServiceOrchestrator } from '../service-management/ServiceOrchestrator.js';
8
+ import { StandardOptions } from '../lib/shared/utils/cli-options.js';
9
+ import { ServiceConfigManager } from '../lib/shared/utils/service-config-manager.js';
10
+ export function registerUpdateCommand(program) {
11
+ 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('--show-config-sources', 'Display all configuration sources and merged result').option('--force', 'Skip confirmation prompts');
12
+
13
+ // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
14
+ StandardOptions.define(command).action(async (servicePath, options) => {
15
+ try {
16
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options);
17
+ const configManager = new ServiceConfigManager({
18
+ verbose: options.verbose,
19
+ quiet: options.quiet,
20
+ json: options.json,
21
+ showSources: options.showConfigSources
22
+ });
23
+ const orchestrator = new ServiceOrchestrator();
24
+
25
+ // Auto-detect service path if not provided
26
+ if (!servicePath) {
27
+ servicePath = await orchestrator.detectServicePath();
28
+ if (!servicePath) {
29
+ output.error('No service path provided and could not auto-detect service directory');
30
+ process.exit(1);
31
+ }
32
+ }
33
+
34
+ // Validate service path with better error handling
35
+ try {
36
+ servicePath = await configManager.validateServicePath(servicePath, orchestrator);
37
+ } catch (error) {
38
+ output.error(error.message);
39
+ if (error.suggestions) {
40
+ output.info('Suggestions:');
41
+ output.list(error.suggestions);
42
+ }
43
+ process.exit(1);
44
+ }
45
+
46
+ // Load and merge all configurations
47
+ const mergedOptions = await configManager.loadServiceConfig(servicePath, options, {
48
+ interactive: false,
49
+ domainName: null,
50
+ cloudflareToken: null,
51
+ cloudflareAccountId: null,
52
+ cloudflareZoneId: null,
53
+ environment: null,
54
+ addFeature: null,
55
+ removeFeature: null,
56
+ regenerateConfigs: false,
57
+ fixErrors: false,
58
+ preview: false,
59
+ force: false
60
+ });
61
+ if (!servicePath) {
62
+ servicePath = await orchestrator.detectServicePath();
63
+ if (!servicePath) {
64
+ output.error('No service path provided and could not auto-detect service directory');
65
+ output.info('Please run this command from within a service directory or specify the path');
66
+ process.exit(1);
67
+ }
68
+ output.info(`Auto-detected service at: ${servicePath}`);
69
+ }
70
+
71
+ // Validate it's a service directory
72
+ const isValid = await orchestrator.validateService(servicePath, {
73
+ customConfig: mergedOptions
74
+ });
75
+ if (!isValid.valid) {
76
+ output.warning('Service has configuration issues. Use --fix-errors to attempt automatic fixes.');
77
+ if (!mergedOptions.fixErrors) {
78
+ output.info('Issues found:');
79
+ output.list(isValid.issues || []);
80
+ process.exit(1);
81
+ }
82
+ }
83
+ if (mergedOptions.interactive) {
84
+ await orchestrator.runInteractiveUpdate(servicePath);
85
+ } else {
86
+ await orchestrator.runNonInteractiveUpdate(servicePath, mergedOptions);
87
+ }
88
+ output.success('Service update completed successfully!');
89
+ } catch (error) {
90
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options || {});
91
+ output.error(`Service update failed: ${error.message}`);
92
+ if (error.details) {
93
+ output.warning(`Details: ${error.details}`);
94
+ }
95
+ if (error.recovery) {
96
+ output.info('Recovery suggestions:');
97
+ output.list(error.recovery);
98
+ }
99
+ process.exit(1);
100
+ }
101
+ });
102
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Validate Command - Validate an existing service configuration
3
+ */
4
+
5
+ import chalk from 'chalk';
6
+ import path from 'path';
7
+ import { ServiceOrchestrator } from '../service-management/ServiceOrchestrator.js';
8
+ import { StandardOptions } from '../lib/shared/utils/cli-options.js';
9
+ import { ServiceConfigManager } from '../lib/shared/utils/service-config-manager.js';
10
+ export function registerValidateCommand(program) {
11
+ const command = program.command('validate <service-path>').description('Validate an existing service configuration').option('--deep-scan', 'Run comprehensive validation checks').option('--export-report <file>', 'Export validation report to JSON file').option('--show-config-sources', 'Display all configuration sources and merged result');
12
+
13
+ // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
14
+ StandardOptions.define(command).action(async (servicePath, options) => {
15
+ try {
16
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options);
17
+ const configManager = new ServiceConfigManager({
18
+ verbose: options.verbose,
19
+ quiet: options.quiet,
20
+ json: options.json,
21
+ showSources: options.showConfigSources
22
+ });
23
+ const orchestrator = new ServiceOrchestrator();
24
+
25
+ // Validate service path with better error handling
26
+ try {
27
+ servicePath = await configManager.validateServicePath(servicePath, orchestrator);
28
+ } catch (error) {
29
+ output.error(error.message);
30
+ if (error.suggestions) {
31
+ output.info('Suggestions:');
32
+ output.list(error.suggestions);
33
+ }
34
+ process.exit(1);
35
+ }
36
+
37
+ // Load and merge all configurations
38
+ const mergedOptions = await configManager.loadServiceConfig(servicePath, options, {
39
+ deepScan: false,
40
+ exportReport: null
41
+ });
42
+ const result = await orchestrator.validateService(servicePath, {
43
+ deepScan: mergedOptions.deepScan,
44
+ exportReport: mergedOptions.exportReport,
45
+ customConfig: mergedOptions.validation // Pass custom validation config
46
+ });
47
+ if (result.valid) {
48
+ output.success('Service configuration is valid');
49
+ } else {
50
+ output.error('Service configuration has issues:');
51
+ output.list(result.issues || []);
52
+ process.exit(1);
53
+ }
54
+
55
+ // Report export success if requested
56
+ if (mergedOptions.exportReport) {
57
+ output.success(`📄 Report exported to: ${mergedOptions.exportReport}`);
58
+ }
59
+ } catch (error) {
60
+ const output = new (await import('../lib/shared/utils/output-formatter.js')).OutputFormatter(options || {});
61
+ output.error(`Validation failed: ${error.message}`);
62
+ process.exit(1);
63
+ }
64
+ });
65
+ }
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ import { SecurityCLI } from '../security/SecurityCLI.js';
3
+ const command = process.argv[2];
4
+ const args = process.argv.slice(3);
5
+ async function main() {
6
+ const cli = new SecurityCLI();
7
+ switch (command) {
8
+ case 'validate':
9
+ {
10
+ const [customer, environment] = args;
11
+ const result = await cli.validateConfiguration(customer, environment);
12
+ if (result.valid) {
13
+ console.log('✅ Security validation passed');
14
+ } else {
15
+ console.log('❌ Security issues found');
16
+ result.securityIssues.forEach(issue => {
17
+ console.log(` ${issue.severity.toUpperCase()}: ${issue.message}`);
18
+ });
19
+ }
20
+ process.exit(result.valid ? 0 : 1);
21
+ break;
22
+ }
23
+ case 'generate-key':
24
+ {
25
+ const [type, lengthStr] = args;
26
+ const length = lengthStr ? parseInt(lengthStr) : undefined;
27
+ const keyResult = cli.generateKey(type, length);
28
+ if (keyResult.success) {
29
+ console.log(`Generated ${keyResult.type}: ${keyResult.key}`);
30
+ } else {
31
+ console.error(`Key generation failed: ${keyResult.error}`);
32
+ process.exit(1);
33
+ }
34
+ break;
35
+ }
36
+ case 'deploy':
37
+ {
38
+ // Check for help flag first
39
+ if (args.includes('--help') || args.includes('-h')) {
40
+ console.log('Deploy with security validation');
41
+ console.log('');
42
+ console.log('Usage:');
43
+ console.log(' clodo-security deploy <customer> <environment> [options]');
44
+ console.log('');
45
+ console.log('Arguments:');
46
+ console.log(' customer Customer name (e.g., wetechfounders)');
47
+ console.log(' environment Target environment (development, staging, production)');
48
+ console.log('');
49
+ console.log('Options:');
50
+ console.log(' --dry-run Simulate deployment without making changes');
51
+ console.log(' --help, -h Display this help message');
52
+ console.log('');
53
+ console.log('Examples:');
54
+ console.log(' clodo-security deploy wetechfounders development');
55
+ console.log(' clodo-security deploy greatidude production --dry-run');
56
+ break;
57
+ }
58
+ const [deployCustomer, deployEnvironment] = args.filter(arg => !arg.startsWith('--'));
59
+ const dryRun = args.includes('--dry-run');
60
+ const deployResult = await cli.deployWithSecurity(deployCustomer, deployEnvironment, {
61
+ dryRun
62
+ });
63
+ if (deployResult.success) {
64
+ console.log(`✅ Deployment ${dryRun ? 'validation' : 'completed'} successfully`);
65
+ } else {
66
+ console.error(`Deployment failed: ${deployResult.error}`);
67
+ process.exit(1);
68
+ }
69
+ break;
70
+ }
71
+ case 'generate-config':
72
+ {
73
+ const [configCustomer, configEnvironment] = args;
74
+ const configResult = cli.generateSecureConfig(configCustomer, configEnvironment);
75
+ if (configResult.success) {
76
+ console.log('Generated secure configuration:');
77
+ console.log(JSON.stringify(configResult.config, null, 2));
78
+ } else {
79
+ console.error(`Config generation failed: ${configResult.error}`);
80
+ process.exit(1);
81
+ }
82
+ break;
83
+ }
84
+ case 'check-readiness':
85
+ {
86
+ const [readyCustomer, readyEnvironment] = args;
87
+ const readinessResult = cli.checkDeploymentReadiness(readyCustomer, readyEnvironment);
88
+ if (readinessResult.ready) {
89
+ console.log('✅ Deployment ready');
90
+ } else {
91
+ console.log('❌ Deployment not ready:');
92
+ readinessResult.issues.forEach(issue => console.log(` - ${issue}`));
93
+ process.exit(1);
94
+ }
95
+ break;
96
+ }
97
+ default:
98
+ console.log('Clodo Framework Security CLI');
99
+ console.log('');
100
+ console.log('Commands:');
101
+ console.log(' validate <customer> <environment> - Validate configuration security');
102
+ console.log(' generate-key [type] [length] - Generate secure key (api/jwt)');
103
+ console.log(' deploy <customer> <environment> - Deploy with security validation');
104
+ console.log(' generate-config <customer> <env> - Generate secure configuration');
105
+ console.log(' check-readiness <customer> <env> - Check deployment readiness');
106
+ console.log('');
107
+ console.log('Examples:');
108
+ console.log(' clodo-security validate tamyla production');
109
+ console.log(' clodo-security generate-key jwt 64');
110
+ console.log(' clodo-security generate-key content-skimmer');
111
+ console.log(' clodo-security deploy tamyla staging --dry-run');
112
+ break;
113
+ }
114
+ }
115
+ main().catch(error => {
116
+ console.error(`Unexpected error: ${error.message}`);
117
+ process.exit(1);
118
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Feature Manager
3
+ * Alias for features.js to maintain compatibility
4
+ */
5
+
6
+ export * from './features.js';
@@ -0,0 +1,26 @@
1
+ {
2
+ "// Comment": "Example configuration for 'npx clodo-service create' command",
3
+ "// Instructions": "Copy this file and customize for your needs, then use: npx clodo-service create --config-file your-config.json",
4
+ "// CLI Override": "Any CLI options passed on command line will override values from this config file",
5
+
6
+ "projectName": "my-cloudflare-worker",
7
+ "description": "A sample Cloudflare Worker project",
8
+ "environment": "development",
9
+ "region": "us-west-1",
10
+ "template": "basic",
11
+ "typescript": true,
12
+ "installDependencies": true,
13
+
14
+ "advanced": {
15
+ "nodeVersion": "18.x",
16
+ "packageManager": "npm",
17
+ "outputDir": "./dist",
18
+ "sourceDir": "./src"
19
+ },
20
+
21
+ "metadata": {
22
+ "author": "your-name",
23
+ "license": "MIT",
24
+ "version": "0.1.0"
25
+ }
26
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "// Comment": "Example configuration for 'npx clodo-service deploy' command",
3
+ "// Instructions": "Copy this file and customize for your needs, then use: npx clodo-service deploy --config-file your-config.json",
4
+ "// EnvVars": "You can use environment variable substitution: ${ENV_VAR_NAME} will be replaced with the value of ENV_VAR_NAME",
5
+
6
+ "domain": "api.example.com",
7
+ "environment": "production",
8
+ "cloudflareToken": "${CLOUDFLARE_TOKEN}",
9
+ "cloudflareZoneId": "${CLOUDFLARE_ZONE_ID}",
10
+
11
+ "deployment": {
12
+ "strategy": "blue-green",
13
+ "replicas": 3,
14
+ "maxConcurrency": 100,
15
+ "timeout": 30000,
16
+ "healthCheckInterval": 5000,
17
+ "rollbackOnFailure": true
18
+ },
19
+
20
+ "routing": {
21
+ "enableLoadBalancing": true,
22
+ "loadBalancingPolicy": "round-robin",
23
+ "corsEnabled": true,
24
+ "corsOrigins": ["https://example.com", "https://app.example.com"]
25
+ },
26
+
27
+ "monitoring": {
28
+ "enableMetrics": true,
29
+ "metricsEndpoint": "https://metrics.example.com",
30
+ "alertOnFailure": true,
31
+ "alertEmail": "alerts@example.com"
32
+ },
33
+
34
+ "security": {
35
+ "enableSSL": true,
36
+ "minTLSVersion": "1.2",
37
+ "enableWAF": true,
38
+ "rateLimit": 1000,
39
+ "rateLimitWindow": 60
40
+ }
41
+ }