@tamyla/clodo-framework 3.1.21 → 3.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +283 -1
  3. package/dist/{bin → cli}/clodo-service.js +47 -15
  4. package/dist/cli/commands/assess.js +183 -0
  5. package/dist/{bin → cli}/commands/create.js +5 -5
  6. package/dist/{bin → cli}/commands/deploy.js +122 -90
  7. package/dist/{bin → cli}/commands/diagnose.js +5 -5
  8. package/dist/cli/commands/helpers/deployment-ui.js +138 -0
  9. package/dist/cli/commands/helpers/deployment-verification.js +250 -0
  10. package/dist/cli/commands/helpers/error-recovery.js +80 -0
  11. package/dist/cli/commands/helpers/resource-detection.js +113 -0
  12. package/dist/{bin → cli}/commands/helpers.js +0 -28
  13. package/dist/cli/commands/init-config.js +57 -0
  14. package/dist/{bin → cli}/commands/update.js +5 -5
  15. package/dist/{bin → cli}/commands/validate.js +5 -5
  16. package/dist/cli/security-cli.js +118 -0
  17. package/dist/config/FeatureManager.js +6 -0
  18. package/dist/config/clodo-create.example.json +26 -0
  19. package/dist/config/clodo-deploy.example.json +41 -0
  20. package/dist/config/clodo-update.example.json +46 -0
  21. package/dist/config/clodo-validate.example.json +41 -0
  22. package/dist/config/customers/template/development.env.template +37 -0
  23. package/dist/config/customers/template/production.env.template +39 -0
  24. package/dist/config/customers/template/staging.env.template +37 -0
  25. package/dist/config/customers.js +28 -26
  26. package/dist/config/domain-examples/README.md +464 -0
  27. package/dist/config/domain-examples/environment-mapped.json +168 -0
  28. package/dist/config/domain-examples/multi-domain.json +144 -0
  29. package/dist/config/domain-examples/single-domain.json +50 -0
  30. package/dist/config/examples +12 -0
  31. package/dist/config/features.js +61 -0
  32. package/dist/config/staging-deployment.json +60 -0
  33. package/dist/config/validation-config.json +347 -0
  34. package/dist/deployment/wrangler-deployer.js +1 -1
  35. package/dist/{bin → lib}/deployment/modules/DeploymentOrchestrator.js +2 -2
  36. package/dist/{bin → lib}/deployment/modules/EnvironmentManager.js +2 -2
  37. package/dist/lib/deployment/orchestration/EnterpriseOrchestrator.js +21 -0
  38. package/dist/lib/shared/cache/configuration-cache.js +82 -0
  39. package/dist/{bin → lib}/shared/cloudflare/domain-discovery.js +1 -1
  40. package/dist/{bin → lib}/shared/cloudflare/domain-manager.js +1 -1
  41. package/dist/{bin → lib}/shared/cloudflare/index.js +1 -1
  42. package/dist/{bin → lib}/shared/cloudflare/ops.js +10 -8
  43. package/dist/{bin → lib}/shared/config/ConfigurationManager.js +23 -1
  44. package/dist/{bin → lib}/shared/config/command-config-manager.js +19 -3
  45. package/dist/{bin → lib}/shared/config/index.js +1 -1
  46. package/dist/{bin → lib}/shared/deployment/credential-collector.js +30 -7
  47. package/dist/lib/shared/deployment/index.js +10 -0
  48. package/dist/lib/shared/deployment/rollback-manager.js +7 -0
  49. package/dist/lib/shared/deployment/utilities/d1-error-recovery.js +177 -0
  50. package/dist/{bin → lib}/shared/deployment/validator.js +40 -10
  51. package/dist/lib/shared/deployment/workflows/deployment-summary.js +214 -0
  52. package/dist/lib/shared/deployment/workflows/interactive-confirmation.js +188 -0
  53. package/dist/lib/shared/deployment/workflows/interactive-database-workflow.js +234 -0
  54. package/dist/lib/shared/deployment/workflows/interactive-domain-info-gatherer.js +240 -0
  55. package/dist/lib/shared/deployment/workflows/interactive-secret-workflow.js +228 -0
  56. package/dist/lib/shared/deployment/workflows/interactive-testing-workflow.js +235 -0
  57. package/dist/lib/shared/deployment/workflows/interactive-validation.js +218 -0
  58. package/dist/lib/shared/error-handling/error-classifier.js +46 -0
  59. package/dist/{bin → lib}/shared/monitoring/health-checker.js +129 -1
  60. package/dist/{bin → lib}/shared/monitoring/memory-manager.js +17 -6
  61. package/dist/{bin → lib}/shared/routing/domain-router.js +1 -1
  62. package/dist/lib/shared/utils/deployment-validator.js +97 -0
  63. package/dist/{bin → lib}/shared/utils/formatters.js +10 -0
  64. package/dist/{bin → lib}/shared/utils/index.js +13 -1
  65. package/dist/{bin → lib}/shared/utils/interactive-prompts.js +34 -18
  66. package/dist/{bin → lib}/shared/utils/progress-manager.js +2 -2
  67. package/dist/lib/shared/utils/progress-spinner.js +53 -0
  68. package/dist/lib/shared/utils/sensitive-redactor.js +91 -0
  69. package/dist/{bin → lib}/shared/validation/ValidationRegistry.js +1 -1
  70. package/dist/migration/MigrationAdapters.js +50 -4
  71. package/dist/orchestration/cross-domain-coordinator.js +5 -5
  72. package/dist/orchestration/multi-domain-orchestrator.js +63 -22
  73. package/dist/security/index.js +2 -2
  74. package/dist/security/patterns/insecure-patterns.js +1 -1
  75. package/dist/service-management/ConfirmationEngine.js +1 -1
  76. package/dist/service-management/ErrorTracker.js +1 -1
  77. package/dist/service-management/InputCollector.js +1 -1
  78. package/dist/service-management/ServiceCreator.js +11 -255
  79. package/dist/service-management/ServiceOrchestrator.js +0 -2
  80. package/dist/service-management/generators/testing/UnitTestsGenerator.js +4 -4
  81. package/dist/service-management/index.js +1 -1
  82. package/dist/utils/cloudflare/ops.js +1 -1
  83. package/dist/utils/constants.js +102 -0
  84. package/dist/utils/deployment/wrangler-config-manager.js +215 -48
  85. package/dist/utils/file-manager.js +1 -1
  86. package/dist/utils/formatters.js +1 -1
  87. package/dist/utils/framework-config.js +2 -2
  88. package/dist/utils/interactive-prompts.js +10 -59
  89. package/dist/utils/logger.js +1 -1
  90. package/dist/version/VersionDetector.js +99 -9
  91. package/dist/worker/integration.js +1 -1
  92. package/package.json +10 -10
  93. package/dist/bin/clodo-service-old.js +0 -868
  94. package/dist/bin/clodo-service-test.js +0 -10
  95. package/dist/bin/commands/assess.js +0 -91
  96. package/dist/bin/database/enterprise-db-manager.js +0 -457
  97. package/dist/bin/deployment/enterprise-deploy.js +0 -877
  98. package/dist/bin/deployment/master-deploy.js +0 -1376
  99. package/dist/bin/deployment/modular-enterprise-deploy.js +0 -466
  100. package/dist/bin/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  101. package/dist/bin/deployment/test-interactive-utils.js +0 -66
  102. package/dist/bin/portfolio/portfolio-manager.js +0 -487
  103. package/dist/bin/security/security-cli.js +0 -108
  104. package/dist/bin/service-management/create-service.js +0 -122
  105. package/dist/bin/service-management/init-service.js +0 -79
  106. package/dist/bin/shared/deployment/index.js +0 -10
  107. package/dist/bin/shared/deployment/rollback-manager.js +0 -523
  108. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +0 -401
  109. package/dist/service-management/ServiceInitializer.js +0 -453
  110. /package/dist/{bin → lib}/database/deployment-db-manager.js +0 -0
  111. /package/dist/{bin → lib}/database/wrangler-d1-manager.js +0 -0
  112. /package/dist/{bin → lib}/deployment/modules/DeploymentConfiguration.js +0 -0
  113. /package/dist/{bin → lib}/deployment/modules/MonitoringIntegration.js +0 -0
  114. /package/dist/{bin → lib}/deployment/modules/ValidationManager.js +0 -0
  115. /package/dist/{bin → lib}/deployment/orchestration/BaseDeploymentOrchestrator.js +0 -0
  116. /package/dist/{bin → lib}/deployment/orchestration/PortfolioOrchestrator.js +0 -0
  117. /package/dist/{bin → lib}/deployment/orchestration/SingleServiceOrchestrator.js +0 -0
  118. /package/dist/{bin → lib}/deployment/orchestration/UnifiedDeploymentOrchestrator.js +0 -0
  119. /package/dist/{bin → lib}/shared/config/cache.js +0 -0
  120. /package/dist/{bin → lib}/shared/config/cloudflare-service-validator.js +0 -0
  121. /package/dist/{bin → lib}/shared/config/manager.js +0 -0
  122. /package/dist/{bin → lib}/shared/config/manifest-loader.js +0 -0
  123. /package/dist/{bin → lib}/shared/database/connection-manager.js +0 -0
  124. /package/dist/{bin → lib}/shared/database/index.js +0 -0
  125. /package/dist/{bin → lib}/shared/database/orchestrator.js +0 -0
  126. /package/dist/{bin → lib}/shared/deployment/auditor.js +0 -0
  127. /package/dist/{bin → lib}/shared/index.js +0 -0
  128. /package/dist/{bin → lib}/shared/logging/Logger.js +0 -0
  129. /package/dist/{bin → lib}/shared/monitoring/index.js +0 -0
  130. /package/dist/{bin → lib}/shared/monitoring/production-monitor.js +0 -0
  131. /package/dist/{bin → lib}/shared/production-tester/api-tester.js +0 -0
  132. /package/dist/{bin → lib}/shared/production-tester/auth-tester.js +0 -0
  133. /package/dist/{bin → lib}/shared/production-tester/core.js +0 -0
  134. /package/dist/{bin → lib}/shared/production-tester/database-tester.js +0 -0
  135. /package/dist/{bin → lib}/shared/production-tester/index.js +0 -0
  136. /package/dist/{bin → lib}/shared/production-tester/load-tester.js +0 -0
  137. /package/dist/{bin → lib}/shared/production-tester/performance-tester.js +0 -0
  138. /package/dist/{bin → lib}/shared/security/api-token-manager.js +0 -0
  139. /package/dist/{bin → lib}/shared/security/index.js +0 -0
  140. /package/dist/{bin → lib}/shared/security/secret-generator.js +0 -0
  141. /package/dist/{bin → lib}/shared/security/secure-token-manager.js +0 -0
  142. /package/dist/{bin → lib}/shared/utils/ErrorHandler.js +0 -0
  143. /package/dist/{bin → lib}/shared/utils/cli-options.js +0 -0
  144. /package/dist/{bin → lib}/shared/utils/config-loader.js +0 -0
  145. /package/dist/{bin → lib}/shared/utils/error-recovery.js +0 -0
  146. /package/dist/{bin → lib}/shared/utils/file-manager.js +0 -0
  147. /package/dist/{bin → lib}/shared/utils/graceful-shutdown-manager.js +0 -0
  148. /package/dist/{bin → lib}/shared/utils/interactive-utils.js +0 -0
  149. /package/dist/{bin → lib}/shared/utils/output-formatter.js +0 -0
  150. /package/dist/{bin → lib}/shared/utils/rate-limiter.js +0 -0
@@ -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
@@ -274,6 +274,26 @@ export class DataServiceAdapter {
274
274
  });
275
275
  }
276
276
 
277
+ /**
278
+ * Query with optional advanced features
279
+ */
280
+ async query(sql, params = [], options = {}) {
281
+ return this._withAsyncMigrationLogging('query', async () => {
282
+ return featureManager.withFeature(FEATURES.ENABLE_ADVANCED_QUERIES, async () => {
283
+ return await this.enhanced.query(sql, params, {
284
+ ...options,
285
+ usePreparedStatements: true,
286
+ enableQueryAnalysis: true
287
+ });
288
+ }, async () => {
289
+ if (this.legacy && this.legacy.query) {
290
+ return await this.legacy.query(sql, params, options);
291
+ }
292
+ return await this.enhanced.queryDirect(sql, params, options);
293
+ });
294
+ });
295
+ }
296
+
277
297
  /**
278
298
  * List with optional advanced pagination
279
299
  */
@@ -310,9 +330,17 @@ export class DataServiceAdapter {
310
330
  * Get migration progress and statistics
311
331
  */
312
332
  getMigrationStats() {
333
+ // Get enhanced service stats and merge with adapter stats
334
+ const enhancedStats = this.enhanced.getMigrationStats ? this.enhanced.getMigrationStats() : {};
313
335
  return {
314
- callCounts: Object.fromEntries(this.migrationState.callCounts),
315
- cacheHitRates: Object.fromEntries(this.migrationState.cacheHitRates),
336
+ callCounts: {
337
+ ...enhancedStats.callCounts,
338
+ ...Object.fromEntries(this.migrationState.callCounts)
339
+ },
340
+ cacheHitRates: {
341
+ ...enhancedStats.cacheHitRates,
342
+ ...Object.fromEntries(this.migrationState.cacheHitRates)
343
+ },
316
344
  performanceGains: Object.fromEntries(this.migrationState.performanceGains),
317
345
  featureUsage: this._getFeatureUsageStats()
318
346
  };
@@ -420,6 +448,16 @@ export class ModuleManagerAdapter {
420
448
  });
421
449
  }
422
450
 
451
+ /**
452
+ * Execute single hook (convenience method)
453
+ */
454
+ async executeHook(hookName, context = {}) {
455
+ const results = await this.executeHooks(hookName, context);
456
+ return results && results.length > 0 ? results[0] : {
457
+ success: false
458
+ };
459
+ }
460
+
423
461
  /**
424
462
  * Get hook metrics if available
425
463
  */
@@ -433,9 +471,17 @@ export class ModuleManagerAdapter {
433
471
  * Get migration statistics
434
472
  */
435
473
  getMigrationStats() {
474
+ // Get enhanced service stats and merge with adapter stats
475
+ const enhancedStats = this.enhanced.getMigrationStats ? this.enhanced.getMigrationStats() : {};
436
476
  return {
437
- hookExecutions: Object.fromEntries(this.migrationState.hookExecutions),
438
- timeoutEvents: Object.fromEntries(this.migrationState.timeoutEvents),
477
+ hookExecutions: {
478
+ ...enhancedStats.hookExecutions,
479
+ ...Object.fromEntries(this.migrationState.hookExecutions)
480
+ },
481
+ timeoutEvents: {
482
+ ...enhancedStats.timeoutEvents,
483
+ ...Object.fromEntries(this.migrationState.timeoutEvents)
484
+ },
439
485
  performanceMetrics: Object.fromEntries(this.migrationState.performanceMetrics),
440
486
  featureUsage: this._getFeatureUsageStats()
441
487
  };
@@ -19,13 +19,13 @@
19
19
 
20
20
  import { access } from 'fs/promises';
21
21
  import { MultiDomainOrchestrator } from './multi-domain-orchestrator.js';
22
- import { DeploymentValidator } from "../../dist/bin/shared/deployment/validator.js";
23
- import { RollbackManager } from "../../dist/bin/shared/deployment/rollback-manager.js";
24
- import { DomainDiscovery } from "../../dist/bin/shared/cloudflare/domain-discovery.js";
22
+ import { DeploymentValidator } from '../lib/shared/deployment/validator.js';
23
+ import { RollbackManager } from '../lib/shared/deployment/rollback-manager.js';
24
+ import { DomainDiscovery } from '../lib/shared/cloudflare/domain-discovery.js';
25
25
  import { DatabaseOrchestrator } from '../database/database-orchestrator.js';
26
26
  import { EnhancedSecretManager } from '../utils/deployment/secret-generator.js';
27
- import { ProductionTester } from "../../dist/bin/shared/production-tester/index.js";
28
- import { DeploymentAuditor } from "../../dist/bin/shared/deployment/auditor.js";
27
+ import { ProductionTester } from '../lib/shared/production-tester/index.js';
28
+ import { DeploymentAuditor } from '../lib/shared/deployment/auditor.js';
29
29
  import { ConfigurationCacheManager } from '../utils/deployment/config-cache.js';
30
30
  export class CrossDomainCoordinator {
31
31
  constructor(options = {}) {
@@ -14,6 +14,7 @@ import { DatabaseOrchestrator } from '../database/database-orchestrator.js';
14
14
  import { EnhancedSecretManager } from '../utils/deployment/secret-generator.js';
15
15
  import { WranglerConfigManager } from '../utils/deployment/wrangler-config-manager.js';
16
16
  import { ConfigurationValidator } from '../security/ConfigurationValidator.js';
17
+ import { buildCustomDomain } from '../utils/constants.js';
17
18
  import { exec } from 'child_process';
18
19
  import { promisify } from 'util';
19
20
  import { join } from 'path';
@@ -34,13 +35,24 @@ export class MultiDomainOrchestrator {
34
35
  this.skipTests = options.skipTests || false;
35
36
  this.parallelDeployments = options.parallelDeployments || 3;
36
37
  this.servicePath = options.servicePath || process.cwd();
38
+ this.serviceName = options.serviceName || 'worker'; // Service name for custom domain
39
+
40
+ // Wrangler config path - allows using customer-specific wrangler.toml files
41
+ // If not specified, wrangler uses the default wrangler.toml in servicePath
42
+ this.wranglerConfigPath = options.wranglerConfigPath;
37
43
 
38
44
  // Cloudflare credentials for API-based operations
39
- this.cloudflareToken = options.cloudflareToken;
40
- this.cloudflareAccountId = options.cloudflareAccountId;
45
+ // Support both legacy individual params and new cloudflareSettings object
46
+ const cfSettings = options.cloudflareSettings || {};
47
+ this.cloudflareToken = options.cloudflareToken || cfSettings.token;
48
+ this.cloudflareAccountId = options.cloudflareAccountId || cfSettings.accountId;
49
+ this.cloudflareZoneId = options.cloudflareZoneId || cfSettings.zoneId;
50
+ this.cloudflareZoneName = options.cloudflareZoneName || cfSettings.zoneName;
41
51
 
42
52
  // Configure wrangler to use API token when available
43
- // This ensures all wrangler operations use the same account as API operations
53
+ // Configure wrangler authentication via environment variables
54
+ // Note: account_id comes from wrangler.toml, not env var
55
+ // (env var would be ignored by wrangler when wrangler.toml has account_id)
44
56
  if (this.cloudflareToken) {
45
57
  process.env.CLOUDFLARE_API_TOKEN = this.cloudflareToken;
46
58
  console.log(`🔑 Configured wrangler to use API token authentication`);
@@ -49,9 +61,12 @@ export class MultiDomainOrchestrator {
49
61
  process.env.CLOUDFLARE_ACCOUNT_ID = this.cloudflareAccountId;
50
62
  console.log(`🔑 Configured wrangler to use account ID: ${this.cloudflareAccountId}`);
51
63
  }
52
- if (this.cloudflareAccountId) {
53
- process.env.CLOUDFLARE_ACCOUNT_ID = this.cloudflareAccountId;
54
- console.log(`🔑 Configured wrangler to use account ID: ${this.cloudflareAccountId}`);
64
+ if (this.cloudflareZoneId) {
65
+ process.env.CLOUDFLARE_ZONE_ID = this.cloudflareZoneId;
66
+ console.log(`🔑 Configured wrangler to use zone ID: ${this.cloudflareZoneId}`);
67
+ }
68
+ if (this.cloudflareZoneName) {
69
+ console.log(`🌐 Deploying to zone: ${this.cloudflareZoneName}`);
55
70
  }
56
71
 
57
72
  // Initialize modular components
@@ -80,7 +95,8 @@ export class MultiDomainOrchestrator {
80
95
  projectRoot: this.servicePath,
81
96
  dryRun: this.dryRun,
82
97
  cloudflareToken: this.cloudflareToken,
83
- cloudflareAccountId: this.cloudflareAccountId
98
+ cloudflareAccountId: this.cloudflareAccountId,
99
+ cloudflareZoneId: this.cloudflareZoneId
84
100
  });
85
101
  this.secretManager = new EnhancedSecretManager({
86
102
  projectRoot: this.servicePath,
@@ -509,15 +525,40 @@ export class MultiDomainOrchestrator {
509
525
  console.log(` 🚀 Deploying worker for ${domain}`);
510
526
  if (this.dryRun) {
511
527
  console.log(` 🔍 DRY RUN: Would deploy worker for ${domain}`);
512
- const subdomain = this.environment === 'production' ? 'api' : `${this.environment}-api`;
528
+ // Use centralized domain template from validation-config.json
529
+ const customUrl = buildCustomDomain(this.serviceName, domain, this.environment);
513
530
  return {
514
- url: `https://${subdomain}.${domain}`,
531
+ url: customUrl,
515
532
  deployed: false,
516
533
  dryRun: true
517
534
  };
518
535
  }
519
536
  try {
520
- // CRITICAL: Ensure environment section exists in wrangler.toml BEFORE deploying
537
+ // Generate/update customer-specific wrangler.toml, then copy to root
538
+ // This implements the architecture where:
539
+ // 1. Customer configs are persistent (deployment history/state)
540
+ // 2. Root wrangler.toml is ephemeral (reflects current active deployment)
541
+ if (this.cloudflareZoneName) {
542
+ console.log(` 🔧 Preparing customer config for zone: ${this.cloudflareZoneName}`);
543
+
544
+ // Generate or update customer config with current deployment parameters
545
+ const customerConfigPath = await this.wranglerConfigManager.generateCustomerConfig(this.cloudflareZoneName, {
546
+ accountId: this.cloudflareAccountId,
547
+ environment: this.environment
548
+ });
549
+
550
+ // Copy customer config to root (ephemeral working copy for this deployment)
551
+ console.log(` 📋 Copying customer config to root wrangler.toml`);
552
+ await this.wranglerConfigManager.copyCustomerConfig(customerConfigPath);
553
+ } else {
554
+ // Fallback: Update root wrangler.toml directly if no zone name available
555
+ console.log(` ⚠️ No zone name available, updating root wrangler.toml directly`);
556
+ if (this.cloudflareAccountId) {
557
+ await this.wranglerConfigManager.setAccountId(this.cloudflareAccountId);
558
+ }
559
+ }
560
+
561
+ // Ensure environment section exists in wrangler.toml
521
562
  console.log(` 📝 Verifying wrangler.toml configuration...`);
522
563
  try {
523
564
  await this.wranglerConfigManager.ensureEnvironment(this.environment);
@@ -526,18 +567,18 @@ export class MultiDomainOrchestrator {
526
567
  // Continue anyway - wrangler will provide clearer error if config is wrong
527
568
  }
528
569
 
529
- // Find wrangler.toml in service path
530
- const wranglerConfigPath = join(this.servicePath, 'wrangler.toml');
531
-
532
- // Build deploy command with environment
570
+ // Build deploy command
571
+ // Note: We already copied customer config to root wrangler.toml above
572
+ // So wrangler will use root wrangler.toml which has the correct account_id
533
573
  let deployCommand = `npx wrangler deploy`;
534
574
 
535
- // Add environment flag for non-production
536
- if (this.environment !== 'production') {
537
- deployCommand += ` --env ${this.environment}`;
538
- }
539
- console.log(` � Executing: ${deployCommand}`);
575
+ // ALWAYS add environment flag to use environment-specific config
576
+ // Even for production, we use [env.production] section which has the correct worker name and DB
577
+ deployCommand += ` --env ${this.environment}`;
578
+ console.log(` 🔧 Executing: ${deployCommand}`);
540
579
  console.log(` 📁 Working directory: ${this.servicePath}`);
580
+ console.log(` 📄 Using wrangler.toml from service root (already updated with customer config)`);
581
+ console.log(` 🌍 Environment: ${this.environment}`);
541
582
 
542
583
  // Execute deployment with timeout
543
584
  const {
@@ -566,9 +607,9 @@ export class MultiDomainOrchestrator {
566
607
  const urlMatch = stdout.match(/https:\/\/[^\s]+/);
567
608
  const workerUrl = urlMatch ? urlMatch[0] : null;
568
609
 
569
- // Also construct custom domain URL
570
- const subdomain = this.environment === 'production' ? 'api' : `${this.environment}-api`;
571
- const customUrl = `https://${subdomain}.${domain}`;
610
+ // Construct custom domain URL using centralized template from validation-config.json
611
+ // Handles all environment patterns: production, staging, development
612
+ const customUrl = buildCustomDomain(this.serviceName, domain, this.environment);
572
613
 
573
614
  // Store URLs in domain state
574
615
  const domainState = this.portfolioState.domainStates.get(domain);
@@ -6,13 +6,13 @@
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 '../lib/shared/utils/index.js';
10
10
  // InteractiveDeploymentConfigurator removed - replaced by InputCollector
11
11
 
12
12
  export { ConfigurationValidator } from './ConfigurationValidator.js';
13
13
  // export { DeploymentManager } - DEPRECATED: Use MultiDomainOrchestrator instead
14
14
  export { SecretGenerator } from './SecretGenerator.js';
15
- export { ErrorHandler } from '../../bin/shared/utils/index.js';
15
+ export { ErrorHandler } from '../lib/shared/utils/index.js';
16
16
  // export { InteractiveDeploymentConfigurator } - DEPRECATED: Use InputCollector instead
17
17
 
18
18
  // Re-export patterns and rules for advanced usage
@@ -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
@@ -34,7 +34,7 @@
34
34
  import { createInterface } from 'readline';
35
35
  import chalk from 'chalk';
36
36
  import { validateServiceName, validateDomainName } from '../utils/validation.js';
37
- import { NameFormatters, UrlFormatters, ResourceFormatters } from "../../dist/bin/shared/utils/Formatters.js";
37
+ import { NameFormatters, UrlFormatters, ResourceFormatters } from '../lib/shared/utils/formatters.js';
38
38
  export class ConfirmationEngine {
39
39
  constructor(options = {}) {
40
40
  this.interactive = options.interactive !== false;
@@ -8,7 +8,7 @@
8
8
  import fs from 'fs/promises';
9
9
  import path from 'path';
10
10
  import chalk from 'chalk';
11
- import { logger } from "../../dist/bin/shared/logging/Logger.js";
11
+ import { logger } from '../lib/shared/logging/Logger.js';
12
12
  export class ErrorTracker {
13
13
  constructor() {
14
14
  this.errors = [];
@@ -15,7 +15,7 @@ import { createInterface } from 'readline';
15
15
  import chalk from 'chalk';
16
16
  import { validateServiceName, validateDomainName } from '../utils/validation.js';
17
17
  import { uiStructuresLoader } from '../utils/ui-structures-loader.js';
18
- import { NameFormatters, UrlFormatters, ResourceFormatters } from "../../dist/bin/shared/utils/Formatters.js";
18
+ import { NameFormatters, UrlFormatters, ResourceFormatters } from '../lib/shared/utils/formatters.js';
19
19
 
20
20
  // Assessment capabilities moved to @tamyla/clodo-orchestration (professional edition)
21
21