@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
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Deployment Validator Utility
3
+ * Pre-deployment validation and prerequisite checking
4
+ * Extracted from clodo-service-old.js for modular reuse
5
+ */
6
+
7
+ import { existsSync } from 'fs';
8
+ import { join } from 'path';
9
+ import chalk from 'chalk';
10
+
11
+ /**
12
+ * Validate deployment prerequisites before proceeding
13
+ * @param {Object} coreInputs - Core deployment inputs
14
+ * @param {Object} options - Deployment options
15
+ * @returns {Promise<boolean>} True if all prerequisites are valid
16
+ */
17
+ export async function validateDeploymentPrerequisites(coreInputs, options) {
18
+ const issues = [];
19
+ console.log(chalk.cyan('\n🔍 Pre-deployment Validation'));
20
+ console.log(chalk.gray('─'.repeat(40)));
21
+
22
+ // Check required fields
23
+ if (!coreInputs.customer) {
24
+ issues.push('Customer name is required');
25
+ }
26
+ if (!coreInputs.environment) {
27
+ issues.push('Environment is required');
28
+ }
29
+ if (!coreInputs.domainName) {
30
+ issues.push('Domain name is required');
31
+ }
32
+ if (!coreInputs.cloudflareToken) {
33
+ issues.push('Cloudflare API token is required');
34
+ }
35
+
36
+ // Check Cloudflare token format (basic validation)
37
+ if (coreInputs.cloudflareToken && !coreInputs.cloudflareToken.startsWith('CLOUDFLARE_API_TOKEN=')) {
38
+ if (coreInputs.cloudflareToken.length < 40) {
39
+ issues.push('Cloudflare API token appears to be invalid (too short)');
40
+ }
41
+ }
42
+
43
+ // Check if service path exists
44
+ if (options.servicePath && options.servicePath !== '.') {
45
+ if (!existsSync(options.servicePath)) {
46
+ issues.push(`Service path does not exist: ${options.servicePath}`);
47
+ }
48
+ }
49
+
50
+ // Check for wrangler.toml if not dry run
51
+ if (!options.dryRun) {
52
+ const wranglerPath = join(options.servicePath || '.', 'wrangler.toml');
53
+ if (!existsSync(wranglerPath)) {
54
+ issues.push('wrangler.toml not found in service directory');
55
+ }
56
+ }
57
+
58
+ // Report issues
59
+ if (issues.length > 0) {
60
+ console.log(chalk.red('\n❌ Validation Failed:'));
61
+ issues.forEach(issue => {
62
+ console.log(chalk.red(` • ${issue}`));
63
+ });
64
+ console.log(chalk.gray('\n─'.repeat(40)));
65
+ return false;
66
+ }
67
+ console.log(chalk.green('✅ All prerequisites validated'));
68
+ console.log(chalk.gray('─'.repeat(40)));
69
+ return true;
70
+ }
71
+
72
+ /**
73
+ * Validate basic deployment inputs
74
+ * @param {Object} inputs - Input object to validate
75
+ * @param {Array<string>} requiredFields - Required field names
76
+ * @returns {Object} Validation result { valid, errors }
77
+ */
78
+ export function validateDeploymentInputs(inputs, requiredFields = ['customer', 'environment', 'domainName', 'cloudflareToken']) {
79
+ const result = {
80
+ valid: true,
81
+ errors: []
82
+ };
83
+
84
+ // Handle null/undefined inputs
85
+ if (!inputs) {
86
+ result.errors.push('Input object is required');
87
+ result.valid = false;
88
+ return result;
89
+ }
90
+ requiredFields.forEach(field => {
91
+ if (!inputs[field]) {
92
+ result.errors.push(`${field} is required`);
93
+ result.valid = false;
94
+ }
95
+ });
96
+ return result;
97
+ }
@@ -118,6 +118,16 @@ export const ResourceFormatters = {
118
118
  */
119
119
  configKey(camelCase) {
120
120
  return NameFormatters.toKebabCase(camelCase);
121
+ },
122
+ /**
123
+ * Format package name for NPM
124
+ * Example: 'my-service' → 'my-service'
125
+ */
126
+ packageName(serviceName) {
127
+ if (!serviceName) return '';
128
+ // For NPM packages, just use the service name as-is
129
+ // Scoped packages would be handled separately (e.g., @company/my-service)
130
+ return serviceName;
121
131
  }
122
132
  };
123
133
 
@@ -16,4 +16,16 @@ export { GracefulShutdownManager, getShutdownManager, initializeGracefulShutdown
16
16
  export { executeWithRateLimit, queueRequest, getRateLimitStatus, clearQueues, RATE_LIMITS } from './rate-limiter.js';
17
17
 
18
18
  // Unified error handling module (Phase 3.2.3d - consolidated from 5 sources)
19
- export { default as ErrorHandler, createErrorResponse, createContextualError, createErrorHandler } from './ErrorHandler.js';
19
+ export { default as ErrorHandler, createErrorResponse, createContextualError, createErrorHandler } from './ErrorHandler.js';
20
+
21
+ // Progress display utilities
22
+ export { showProgressSpinner, showProgressWithSpinner } from './progress-spinner.js';
23
+
24
+ // Deployment validation
25
+ export { validateDeploymentPrerequisites, validateDeploymentInputs } from './deployment-validator.js';
26
+
27
+ // Sensitive information redaction
28
+ export { redactSensitiveInfo, redactSensitiveObject } from './sensitive-redactor.js';
29
+
30
+ // Configuration loading
31
+ export { ConfigLoader } from './config-loader.js';
@@ -98,6 +98,7 @@ export function showProgress(message, steps = ['⏳', '⚡', '✅']) {
98
98
 
99
99
  /**
100
100
  * Ask for sensitive input (like API tokens) with hidden input
101
+ * Supports pasting with Ctrl+V or right-click paste
101
102
  */
102
103
  export function askPassword(question) {
103
104
  return new Promise(resolve => {
@@ -107,26 +108,41 @@ export function askPassword(question) {
107
108
  // Hide input for sensitive data
108
109
  process.stdin.setRawMode(true);
109
110
  process.stdin.resume();
111
+ process.stdin.setEncoding('utf8');
110
112
  let password = '';
111
- const onData = char => {
112
- const charCode = char[0];
113
- if (charCode === 13) {
114
- // Enter key
115
- process.stdin.setRawMode(false);
116
- process.stdin.pause();
117
- process.stdin.removeListener('data', onData);
118
- process.stdout.write('\n');
119
- resolve(password);
120
- } else if (charCode === 127 || charCode === 8) {
121
- // Backspace
122
- if (password.length > 0) {
123
- password = password.slice(0, -1);
124
- process.stdout.write('\b \b');
113
+ const onData = chunk => {
114
+ // Handle multi-character input (paste operations)
115
+ for (let i = 0; i < chunk.length; i++) {
116
+ const char = chunk[i];
117
+ const charCode = char.charCodeAt(0);
118
+ if (charCode === 13 || charCode === 10) {
119
+ // Enter key (CR or LF)
120
+ process.stdin.setRawMode(false);
121
+ process.stdin.pause();
122
+ process.stdin.removeListener('data', onData);
123
+ process.stdout.write('\n');
124
+ resolve(password);
125
+ return;
126
+ } else if (charCode === 127 || charCode === 8) {
127
+ // Backspace
128
+ if (password.length > 0) {
129
+ password = password.slice(0, -1);
130
+ process.stdout.write('\b \b');
131
+ }
132
+ } else if (charCode === 3) {
133
+ // Ctrl+C
134
+ process.stdin.setRawMode(false);
135
+ process.stdin.pause();
136
+ process.stdin.removeListener('data', onData);
137
+ process.stdout.write('\n');
138
+ console.log('\nOperation cancelled');
139
+ process.exit(0);
140
+ } else if (charCode >= 32 && charCode <= 126) {
141
+ // Printable characters
142
+ password += char;
143
+ process.stdout.write('*');
125
144
  }
126
- } else if (charCode >= 32 && charCode <= 126) {
127
- // Printable characters
128
- password += char.toString();
129
- process.stdout.write('*');
145
+ // Ignore other control characters (allows paste to work)
130
146
  }
131
147
  };
132
148
  process.stdin.on('data', onData);
@@ -71,11 +71,11 @@ export class ProgressManager {
71
71
  * @returns {ProgressManager} This instance for chaining
72
72
  */
73
73
  nextStep(stepName = null) {
74
+ this.currentStep++;
75
+ this.stepStartTime = Date.now();
74
76
  if (this.quiet) {
75
77
  return this;
76
78
  }
77
- this.currentStep++;
78
- this.stepStartTime = Date.now();
79
79
  const name = stepName || this.steps[this.currentStep - 1] || `Step ${this.currentStep}`;
80
80
  const progress = this.totalSteps > 0 ? Math.round(this.currentStep / this.totalSteps * 100) : 0;
81
81
  if (this.output) {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Progress Spinner Utility
3
+ * Enhanced progress display with spinner animation
4
+ * Extracted from clodo-service-old.js for modular reuse
5
+ */
6
+
7
+ import chalk from 'chalk';
8
+
9
+ /**
10
+ * Display progress with animated spinner
11
+ * @param {string} message - Progress message to display
12
+ * @param {number} duration - Duration in milliseconds (default: 2000)
13
+ * @returns {Promise} Resolves when progress completes
14
+ */
15
+ export function showProgressSpinner(message, duration = 2000) {
16
+ return new Promise(resolve => {
17
+ process.stdout.write(chalk.cyan(`⏳ ${message}...`));
18
+ const spinner = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
19
+ let i = 0;
20
+ const interval = setInterval(() => {
21
+ process.stdout.write(`\r${chalk.cyan(spinner[i])} ${message}...`);
22
+ i = (i + 1) % spinner.length;
23
+ }, 100);
24
+ setTimeout(() => {
25
+ clearInterval(interval);
26
+ process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
27
+ resolve();
28
+ }, duration);
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Display progress with custom spinner characters
34
+ * @param {string} message - Progress message
35
+ * @param {Array<string>} spinnerChars - Custom spinner characters
36
+ * @param {number} duration - Duration in milliseconds
37
+ * @returns {Promise} Resolves when complete
38
+ */
39
+ export function showProgressWithSpinner(message, spinnerChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'], duration = 2000) {
40
+ return new Promise(resolve => {
41
+ process.stdout.write(chalk.cyan(`⏳ ${message}...`));
42
+ let i = 0;
43
+ const interval = setInterval(() => {
44
+ process.stdout.write(`\r${chalk.cyan(spinnerChars[i])} ${message}...`);
45
+ i = (i + 1) % spinnerChars.length;
46
+ }, 100);
47
+ setTimeout(() => {
48
+ clearInterval(interval);
49
+ process.stdout.write(`\r${chalk.green('✅')} ${message}... Done!\n`);
50
+ resolve();
51
+ }, duration);
52
+ });
53
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Sensitive Information Redactor
3
+ * Advanced pattern-based redaction for logs and output
4
+ * Extracted from clodo-service-old.js for modular reuse
5
+ */
6
+
7
+ /**
8
+ * Redact sensitive information from text using pattern matching
9
+ * @param {string} text - Text to redact
10
+ * @returns {string} Redacted text
11
+ */
12
+ export function redactSensitiveInfo(text) {
13
+ if (typeof text !== 'string') return text;
14
+
15
+ // Patterns to redact
16
+ const patterns = [
17
+ // Cloudflare API tokens
18
+ [/(CLOUDFLARE_API_TOKEN=?)(\w{20,})/gi, '$1[REDACTED]'],
19
+ // Generic API tokens/keys - require minimum length
20
+ [/(token|api[_-]?token|api[_-]?key|auth[_-]?token)["']?[:=]\s*([a-zA-Z0-9_-]{6,})/gi, '$1: [REDACTED]'],
21
+ // Passwords - require minimum length
22
+ [/(password|passwd|pwd)["']?[:=]\s*([^"'\s]{4,})/gi, '$1: [REDACTED]'],
23
+ // Secrets - require minimum length
24
+ [/(secret|key)["']?[:=]\s*([a-zA-Z0-9_-]{6,})/gi, '$1: [REDACTED]'],
25
+ // Account IDs (partial redaction) - match 8+ characters
26
+ [/(account[_-]?id|zone[_-]?id)["']?[:=]\s*["']?([a-zA-Z0-9]{8})([a-zA-Z0-9]*)/gi, '$1: $2[REDACTED]']];
27
+ let redacted = text;
28
+ patterns.forEach(([pattern, replacement]) => {
29
+ redacted = redacted.replace(pattern, replacement);
30
+ });
31
+ return redacted;
32
+ }
33
+
34
+ /**
35
+ * Redact sensitive information from an object recursively
36
+ * @param {any} obj - Object to redact
37
+ * @param {Set} visited - Set of visited objects to prevent circular references
38
+ * @returns {any} Redacted object
39
+ */
40
+ export function redactSensitiveObject(obj, visited = new Set()) {
41
+ // Handle circular references by returning a placeholder
42
+ if (obj && typeof obj === 'object') {
43
+ if (visited.has(obj)) {
44
+ return '[CIRCULAR REFERENCE]';
45
+ }
46
+ visited.add(obj);
47
+ }
48
+ if (typeof obj === 'string') {
49
+ return redactSensitiveInfo(obj);
50
+ }
51
+ if (Array.isArray(obj)) {
52
+ // Process each array element individually
53
+ return obj.map(item => redactSensitiveObject(item, visited));
54
+ }
55
+ if (obj && typeof obj === 'object') {
56
+ const redacted = {};
57
+ for (const [key, value] of Object.entries(obj)) {
58
+ const lowerKey = key.toLowerCase();
59
+ // Special handling for accountId and zoneId - allow partial redaction via regex
60
+ if (lowerKey.includes('accountid') || lowerKey.includes('zoneid')) {
61
+ if (typeof value === 'string') {
62
+ // Apply partial redaction for account/zone IDs
63
+ redacted[key] = value.replace(/^([a-zA-Z0-9]{8})([a-zA-Z0-9]*)$/, '$1[REDACTED]');
64
+ } else {
65
+ redacted[key] = redactSensitiveObject(value, visited);
66
+ }
67
+ } else if (isSensitiveKey(key)) {
68
+ if (Array.isArray(value)) {
69
+ // Redact each element in sensitive arrays
70
+ redacted[key] = value.map(() => '[REDACTED]');
71
+ } else {
72
+ redacted[key] = '[REDACTED]';
73
+ }
74
+ } else {
75
+ redacted[key] = redactSensitiveObject(value, visited);
76
+ }
77
+ }
78
+ return redacted;
79
+ }
80
+ return obj;
81
+ }
82
+
83
+ /**
84
+ * Check if a key name indicates sensitive information
85
+ * @param {string} key - Key name to check
86
+ * @returns {boolean} True if key is sensitive
87
+ */
88
+ function isSensitiveKey(key) {
89
+ const sensitiveKeys = ['password', 'passwd', 'pwd', 'secret', 'key', 'token', 'apikey', 'cloudflaretoken', 'apitoken', 'authkey', 'privatekey'];
90
+ return sensitiveKeys.some(sensitive => key.toLowerCase().includes(sensitive.toLowerCase()));
91
+ }
@@ -8,7 +8,7 @@
8
8
  /**
9
9
  * Import validators from src/utils (source of truth)
10
10
  */
11
- import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from "../../../utils/validation.js";
11
+ import { validateServiceName, validateDomainName, validateCloudflareToken, validateCloudflareId, validateServiceType, validateEnvironment } from '../../../utils/validation.js';
12
12
 
13
13
  /**
14
14
  * Validation Registry - Single source of truth for all validators
@@ -6,7 +6,7 @@
6
6
  import { ConfigurationValidator } from './ConfigurationValidator.js';
7
7
  // DeploymentManager removed - replaced by MultiDomainOrchestrator + WranglerConfigManager
8
8
  import { SecretGenerator } from './SecretGenerator.js';
9
- import { ErrorHandler } from "../../dist/bin/shared/utils/index.js";
9
+ import { ErrorHandler } from '../../bin/shared/utils/index.js';
10
10
  // InteractiveDeploymentConfigurator removed - replaced by InputCollector
11
11
 
12
12
  export { ConfigurationValidator } from './ConfigurationValidator.js';
@@ -5,7 +5,7 @@
5
5
 
6
6
  export const INSECURE_PATTERNS = {
7
7
  // Development/dummy API keys
8
- DUMMY_API_KEYS: ['content-skimmer-dev-key', 'logger-service-dev-key', 'auth-service-dev-key', 'test-key', 'dev-key', 'dummy-key', 'placeholder-key', 'example-key', 'sample-key', 'demo-key', 'test-api-key-*', 'dummy-*-key', 'dev-*-secret', 'placeholder-*', 'example-*-token', 'fake-*-credential', 'mock-*-password'],
8
+ DUMMY_API_KEYS: ['content-skimmer-dev-key', 'logger-service-dev-key', 'auth-service-dev-key', 'test-key', 'dev-key', 'dummy-key', 'dummy-api-key', 'placeholder-key', 'example-key', 'sample-key', 'demo-key', 'test-api-key-*', 'dummy-*-key', 'dev-*-secret', 'placeholder-*', 'example-*-token', 'fake-*-credential', 'mock-*-password'],
9
9
  // Weak secrets (common insecure values)
10
10
  WEAK_SECRETS: ['secret', 'password', '123456', 'admin', 'test', 'changeme', 'default', 'password123', 'admin123', 'root', 'guest'],
11
11
  // Development URLs that shouldn't be in production
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Centralized Constants
3
+ * Loads constants from validation-config.json to avoid duplication
4
+ * Provides easy access to domain templates, timeouts, and other config
5
+ */
6
+
7
+ import { readFileSync } from 'fs';
8
+ import { join, dirname } from 'path';
9
+ import { fileURLToPath } from 'url';
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = dirname(__filename);
12
+
13
+ // Load validation config
14
+ let validationConfig;
15
+ try {
16
+ const configPath = join(__dirname, '..', '..', 'config', 'validation-config.json');
17
+ validationConfig = JSON.parse(readFileSync(configPath, 'utf-8'));
18
+ } catch (error) {
19
+ console.warn('⚠️ Could not load validation-config.json, using fallback constants');
20
+ validationConfig = null;
21
+ }
22
+
23
+ /**
24
+ * Get domain template for environment
25
+ * @param {string} environment - Environment name (development, staging, production)
26
+ * @returns {string} Domain template pattern
27
+ */
28
+ export function getDomainTemplate(environment = 'production') {
29
+ if (validationConfig?.environments?.[environment]?.domainTemplate) {
30
+ return validationConfig.environments[environment].domainTemplate;
31
+ }
32
+
33
+ // Fallback templates if config not available
34
+ const fallbacks = {
35
+ production: '{service}.{domain}',
36
+ staging: 'staging-{service}.{domain}',
37
+ development: 'dev-{service}.{domain}'
38
+ };
39
+ return fallbacks[environment] || fallbacks.production;
40
+ }
41
+
42
+ /**
43
+ * Build custom domain URL from template
44
+ * @param {string} serviceName - Service name
45
+ * @param {string} domain - Base domain (e.g., clodo.dev)
46
+ * @param {string} environment - Environment name
47
+ * @returns {string} Full custom domain URL
48
+ */
49
+ export function buildCustomDomain(serviceName, domain, environment = 'production') {
50
+ const template = getDomainTemplate(environment);
51
+ const subdomain = template.replace('{service}', serviceName).replace('{domain}', domain);
52
+ return `https://${subdomain}`;
53
+ }
54
+
55
+ /**
56
+ * Get environment-specific worker suffix
57
+ * @param {string} environment - Environment name
58
+ * @returns {string} Worker suffix (e.g., '-dev', '-staging', '')
59
+ */
60
+ export function getWorkerSuffix(environment = 'production') {
61
+ return validationConfig?.environments?.[environment]?.workerSuffix || '';
62
+ }
63
+
64
+ /**
65
+ * Get environment-specific database suffix
66
+ * @param {string} environment - Environment name
67
+ * @returns {string} Database suffix (e.g., '-dev', '-staging', '')
68
+ */
69
+ export function getDatabaseSuffix(environment = 'production') {
70
+ return validationConfig?.environments?.[environment]?.databaseSuffix || '';
71
+ }
72
+
73
+ /**
74
+ * Get timing configuration
75
+ * @param {string} key - Timing key
76
+ * @returns {number} Timeout in milliseconds
77
+ */
78
+ export function getTimeout(key) {
79
+ return validationConfig?.timing?.[key] || 30000; // Default 30s
80
+ }
81
+
82
+ /**
83
+ * Get all service types
84
+ * @returns {string[]} Array of valid service types
85
+ */
86
+ export function getServiceTypes() {
87
+ return validationConfig?.validation?.serviceTypes || ['data-service', 'auth-service', 'content-service', 'api-gateway', 'static-site', 'generic'];
88
+ }
89
+
90
+ /**
91
+ * Export full config for direct access if needed
92
+ */
93
+ export const VALIDATION_CONFIG = validationConfig;
94
+
95
+ /**
96
+ * Common constants
97
+ */
98
+ export const CONSTANTS = {
99
+ DEFAULT_ENVIRONMENT: 'production',
100
+ SUPPORTED_ENVIRONMENTS: ['development', 'staging', 'production'],
101
+ WORKERS_DEV_SUFFIX: '.workers.dev'
102
+ };