@tamyla/clodo-framework 3.1.4 → 3.1.8

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 (62) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/bin/clodo-service.js +29 -989
  3. package/bin/database/enterprise-db-manager.js +7 -5
  4. package/bin/security/security-cli.js +0 -0
  5. package/bin/service-management/create-service.js +0 -0
  6. package/bin/service-management/init-service.js +0 -0
  7. package/bin/shared/cloudflare/domain-discovery.js +11 -10
  8. package/bin/shared/cloudflare/ops.js +1 -1
  9. package/bin/shared/config/ConfigurationManager.js +539 -0
  10. package/bin/shared/config/index.js +13 -1
  11. package/bin/shared/database/connection-manager.js +2 -2
  12. package/bin/shared/database/orchestrator.js +5 -4
  13. package/bin/shared/deployment/auditor.js +9 -8
  14. package/bin/shared/logging/Logger.js +214 -0
  15. package/bin/shared/monitoring/production-monitor.js +21 -9
  16. package/bin/shared/utils/ErrorHandler.js +675 -0
  17. package/bin/shared/utils/error-recovery.js +33 -13
  18. package/bin/shared/utils/file-manager.js +162 -0
  19. package/bin/shared/utils/formatters.js +247 -0
  20. package/bin/shared/utils/index.js +14 -4
  21. package/bin/shared/validation/ValidationRegistry.js +143 -0
  22. package/dist/deployment/auditor.js +23 -8
  23. package/dist/deployment/orchestration/BaseDeploymentOrchestrator.js +426 -0
  24. package/dist/deployment/orchestration/EnterpriseOrchestrator.js +401 -0
  25. package/dist/deployment/orchestration/PortfolioOrchestrator.js +273 -0
  26. package/dist/deployment/orchestration/SingleServiceOrchestrator.js +231 -0
  27. package/dist/deployment/orchestration/UnifiedDeploymentOrchestrator.js +662 -0
  28. package/dist/deployment/orchestration/index.js +17 -0
  29. package/dist/index.js +12 -0
  30. package/dist/orchestration/modules/DomainResolver.js +8 -6
  31. package/dist/orchestration/multi-domain-orchestrator.js +13 -1
  32. package/dist/security/index.js +2 -2
  33. package/dist/service-management/ConfirmationEngine.js +8 -7
  34. package/dist/service-management/ErrorTracker.js +7 -2
  35. package/dist/service-management/InputCollector.js +31 -16
  36. package/dist/service-management/ServiceCreator.js +22 -7
  37. package/dist/service-management/ServiceInitializer.js +12 -18
  38. package/dist/shared/cloudflare/domain-discovery.js +11 -10
  39. package/dist/shared/cloudflare/ops.js +1 -1
  40. package/dist/shared/config/ConfigurationManager.js +519 -0
  41. package/dist/shared/config/index.js +5 -1
  42. package/dist/shared/database/connection-manager.js +2 -2
  43. package/dist/shared/database/orchestrator.js +13 -4
  44. package/dist/shared/deployment/auditor.js +23 -8
  45. package/dist/shared/logging/Logger.js +209 -0
  46. package/dist/shared/monitoring/production-monitor.js +24 -8
  47. package/dist/{utils → shared/utils}/ErrorHandler.js +306 -28
  48. package/dist/shared/utils/error-recovery.js +33 -13
  49. package/dist/shared/utils/file-manager.js +155 -0
  50. package/dist/shared/utils/formatters.js +215 -0
  51. package/dist/shared/utils/index.js +14 -4
  52. package/dist/shared/validation/ValidationRegistry.js +126 -0
  53. package/dist/utils/config/unified-config-manager.js +14 -12
  54. package/dist/utils/deployment/config-cache.js +3 -1
  55. package/dist/utils/deployment/secret-generator.js +32 -29
  56. package/dist/utils/framework-config.js +6 -3
  57. package/dist/utils/ui-structures-loader.js +3 -0
  58. package/dist/worker/integration.js +11 -1
  59. package/package.json +31 -3
  60. package/dist/config/FeatureManager.js +0 -426
  61. package/dist/config/features.js +0 -230
  62. package/dist/utils/error-recovery.js +0 -240
@@ -63,12 +63,14 @@ export class DomainResolver {
63
63
  warnings: []
64
64
  };
65
65
  try {
66
- // Validate required environment variables
67
- const requiredEnvVars = ['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID'];
68
- const missing = requiredEnvVars.filter(envVar => !process.env[envVar]);
69
- if (missing.length > 0) {
70
- validation.valid = false;
71
- validation.issues.push(`Missing required environment variables: ${missing.join(', ')}`);
66
+ // Validate Cloudflare token
67
+ if (!process.env.CLOUDFLARE_API_TOKEN) {
68
+ validation.warnings.push('CLOUDFLARE_API_TOKEN not yet configured (will be set during deployment)');
69
+ }
70
+
71
+ // Validate Cloudflare account ID
72
+ if (!process.env.CLOUDFLARE_ACCOUNT_ID) {
73
+ validation.warnings.push('CLOUDFLARE_ACCOUNT_ID not yet configured (will be set during deployment)');
72
74
  }
73
75
 
74
76
  // Validate domain format
@@ -45,6 +45,14 @@ export class MultiDomainOrchestrator {
45
45
  process.env.CLOUDFLARE_API_TOKEN = this.cloudflareToken;
46
46
  console.log(`🔑 Configured wrangler to use API token authentication`);
47
47
  }
48
+ if (this.cloudflareAccountId) {
49
+ process.env.CLOUDFLARE_ACCOUNT_ID = this.cloudflareAccountId;
50
+ console.log(`🔑 Configured wrangler to use account ID: ${this.cloudflareAccountId}`);
51
+ }
52
+ if (this.cloudflareAccountId) {
53
+ process.env.CLOUDFLARE_ACCOUNT_ID = this.cloudflareAccountId;
54
+ console.log(`🔑 Configured wrangler to use account ID: ${this.cloudflareAccountId}`);
55
+ }
48
56
 
49
57
  // Initialize modular components
50
58
  this.domainResolver = new DomainResolver({
@@ -161,14 +169,18 @@ export class MultiDomainOrchestrator {
161
169
  /**
162
170
  * Deploy to single domain using modular deployment coordinator
163
171
  * @param {string} domain - Domain to deploy
172
+ * @param {Object} deploymentOptions - Deployment configuration options
164
173
  * @returns {Promise<Object>} Deployment result
165
174
  */
166
- async deploySingleDomain(domain) {
175
+ async deploySingleDomain(domain, deploymentOptions = {}) {
167
176
  const domainState = this.portfolioState.domainStates.get(domain);
168
177
  if (!domainState) {
169
178
  throw new Error(`Domain ${domain} not found in portfolio`);
170
179
  }
171
180
 
181
+ // Store deployment options in domain state for handlers to access
182
+ domainState.deploymentOptions = deploymentOptions;
183
+
172
184
  // Create handlers that delegate to our legacy methods for backward compatibility
173
185
  const handlers = {
174
186
  validation: d => this.validateDomainPrerequisites(d),
@@ -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 '../utils/ErrorHandler.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';
13
13
  // export { DeploymentManager } - DEPRECATED: Use MultiDomainOrchestrator instead
14
14
  export { SecretGenerator } from './SecretGenerator.js';
15
- export { ErrorHandler } from '../utils/ErrorHandler.js';
15
+ export { ErrorHandler } from '../../bin/shared/utils/index.js';
16
16
  // export { InteractiveDeploymentConfigurator } - DEPRECATED: Use InputCollector instead
17
17
 
18
18
  // Re-export patterns and rules for advanced usage
@@ -34,6 +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 '../../bin/shared/utils/Formatters.js';
37
38
  export class ConfirmationEngine {
38
39
  constructor(options = {}) {
39
40
  this.interactive = options.interactive !== false;
@@ -82,17 +83,17 @@ export class ConfirmationEngine {
82
83
  // 4. Author - Default framework author
83
84
  author: 'Clodo Framework',
84
85
  // 5-7. URLs - Derived from domain and service name
85
- productionUrl: `https://${serviceName}.${domainName}`,
86
- stagingUrl: `https://${serviceName}-staging.${domainName}`,
87
- developmentUrl: `https://${serviceName}-dev.${domainName}`,
86
+ productionUrl: UrlFormatters.buildProductionUrl(serviceName, domainName),
87
+ stagingUrl: UrlFormatters.buildStagingUrl(serviceName, domainName),
88
+ developmentUrl: UrlFormatters.buildDevUrl(serviceName, domainName),
88
89
  // 8. Features - Based on service type
89
90
  features: this.generateFeaturesForType(serviceType),
90
91
  // 9. Database Name - Cloudflare D1 naming
91
- databaseName: `${serviceName}-db`,
92
+ databaseName: ResourceFormatters.databaseName(serviceName),
92
93
  // 10. Worker Name - Cloudflare Worker naming
93
- workerName: `${serviceName}-worker`,
94
+ workerName: ResourceFormatters.workerName(serviceName),
94
95
  // 11. Package Name - NPM package naming
95
- packageName: `@clodo/${serviceName}`,
96
+ packageName: ResourceFormatters.packageName(serviceName),
96
97
  // 12. Git Repository URL - GitHub naming
97
98
  gitRepositoryUrl: `https://github.com/tamylaa/${serviceName}`,
98
99
  // 13. Documentation URL - Based on domain
@@ -319,7 +320,7 @@ export class ConfirmationEngine {
319
320
  * Generate display name from service name
320
321
  */
321
322
  generateDisplayName(serviceName) {
322
- return serviceName.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
323
+ return NameFormatters.toDisplayName(serviceName);
323
324
  }
324
325
 
325
326
  /**
@@ -8,6 +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 '../../bin/shared/logging/Logger.js';
11
12
  export class ErrorTracker {
12
13
  constructor() {
13
14
  this.errors = [];
@@ -46,7 +47,9 @@ export class ErrorTracker {
46
47
 
47
48
  // Log to file asynchronously (don't block)
48
49
  this.logErrorToFile(errorEntry).catch(err => {
49
- console.warn(chalk.yellow(`Failed to write error log: ${err.message}`));
50
+ logger.warn('Failed to write error log', {
51
+ error: err.message
52
+ });
50
53
  });
51
54
  return errorEntry;
52
55
  }
@@ -155,7 +158,9 @@ export class ErrorTracker {
155
158
  await fs.appendFile(this.errorLogPath, logEntry);
156
159
  } catch (error) {
157
160
  // If we can't write to the log file, at least show a warning
158
- console.warn(chalk.yellow(`Could not write to error log: ${error.message}`));
161
+ logger.warn('Could not write to error log', {
162
+ error: error.message
163
+ });
159
164
  }
160
165
  }
161
166
 
@@ -15,6 +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 '../../bin/shared/utils/Formatters.js';
18
19
 
19
20
  // Assessment capabilities moved to @tamyla/clodo-orchestration (professional edition)
20
21
 
@@ -122,12 +123,12 @@ export class InputCollector {
122
123
  console.log(chalk.white('The following will be automatically generated from your inputs:\n'));
123
124
  const autoTemplate = uiStructuresLoader.getAutomatedGenerationTemplate();
124
125
  if (autoTemplate) {
125
- console.log(chalk.gray(`📊 ${autoTemplate.collectionStrategy.inputCount} configurations will be generated automatically`));
126
+ console.log(chalk.gray(`📊 ${autoTemplate.template.inputCount} configurations will be generated automatically`));
126
127
  console.log(chalk.gray(`⏱️ Estimated time: ${autoTemplate.template.estimatedTime}`));
127
128
 
128
129
  // Show some examples of what will be automated
129
130
  result.automatedGenerations = {
130
- count: autoTemplate.collectionStrategy.inputCount,
131
+ count: autoTemplate.template.inputCount,
131
132
  estimatedTime: autoTemplate.template.estimatedTime,
132
133
  examples: ['Database connection strings', 'Environment variables', 'API endpoints', 'Security configurations', 'Deployment scripts']
133
134
  };
@@ -148,12 +149,15 @@ export class InputCollector {
148
149
  * Generate smart defaults based on core inputs
149
150
  */
150
151
  generateSmartDefault(inputId, coreInputs) {
151
- const serviceName = coreInputs.serviceName?.value || '';
152
- const environment = coreInputs.environment?.value || 'development';
153
- const domainName = coreInputs.domainName?.value || '';
152
+ const serviceName = coreInputs['service-name']?.value || coreInputs.serviceName?.value || '';
153
+ const environment = coreInputs['environment']?.value || coreInputs.environment?.value || 'development';
154
+ const domainName = coreInputs['domain-name']?.value || coreInputs.domainName?.value || '';
155
+ const serviceType = coreInputs['service-type']?.value || coreInputs.serviceType?.value || '';
156
+ const customerName = coreInputs['customer-name']?.value || coreInputs.customerName?.value || '';
157
+ const cloudflareToken = coreInputs['cloudflare-api-token']?.value || coreInputs.cloudflareApiToken?.value || '';
154
158
  switch (inputId) {
155
159
  case 'display-name':
156
- return serviceName ? serviceName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : '';
160
+ return serviceName ? NameFormatters.toDisplayName(serviceName) : '';
157
161
  case 'description':
158
162
  return `A service built with CLODO Framework`;
159
163
  case 'version':
@@ -161,19 +165,21 @@ export class InputCollector {
161
165
  case 'author':
162
166
  return 'CLODO Framework';
163
167
  case 'production-url':
164
- return domainName ? `https://api.${domainName}` : '';
168
+ return domainName && serviceName ? UrlFormatters.buildProductionUrl(serviceName, domainName) : '';
165
169
  case 'staging-url':
166
- return domainName && serviceName ? `https://${serviceName}-staging.${domainName}` : '';
170
+ return domainName && serviceName ? UrlFormatters.buildStagingUrl(serviceName, domainName) : '';
167
171
  case 'development-url':
168
- return domainName && serviceName ? `https://${serviceName}-dev.${domainName}` : '';
172
+ return domainName && serviceName ? UrlFormatters.buildDevUrl(serviceName, domainName) : '';
169
173
  case 'service-directory':
170
174
  return serviceName ? `./services/${serviceName}` : '';
171
175
  case 'database-name':
172
- return serviceName ? `${serviceName}-db` : '';
176
+ return serviceName ? ResourceFormatters.databaseName(serviceName) : '';
173
177
  case 'worker-name':
174
- return serviceName ? `${serviceName}-worker` : '';
178
+ return serviceName ? ResourceFormatters.workerName(serviceName) : '';
175
179
  case 'log-level':
176
180
  return environment === 'production' ? 'warn' : environment === 'staging' ? 'info' : 'debug';
181
+ case 'cors-policy':
182
+ return domainName ? `https://${domainName}` : '*';
177
183
  case 'env-prefix':
178
184
  return environment === 'production' ? 'PROD_' : environment === 'staging' ? 'STAGING_' : 'DEV_';
179
185
  default:
@@ -195,7 +201,7 @@ export class InputCollector {
195
201
  * Format field names for display
196
202
  */
197
203
  formatFieldName(inputId) {
198
- return inputId.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
204
+ return NameFormatters.toDisplayName(inputId);
199
205
  }
200
206
 
201
207
  /**
@@ -589,16 +595,25 @@ export class InputCollector {
589
595
  }
590
596
 
591
597
  /**
592
- * Collect inputs and return flat core inputs object
593
- * Used by CLI for deployment
598
+ * Collect inputs and return full three-tier result
599
+ * Used by CLI for comprehensive service operations
594
600
  */
595
601
  async collect() {
596
602
  const result = await this.collectInputsWithTransparency();
597
- // Flatten the core inputs from {id: {value, ...}} to {id: value}
603
+
604
+ // For CLI compatibility, also provide flat coreInputs
598
605
  const flatCoreInputs = {};
599
606
  for (const [key, inputObj] of Object.entries(result.coreInputs)) {
600
607
  flatCoreInputs[key] = inputObj.value;
601
608
  }
602
- return flatCoreInputs;
609
+
610
+ // Merge smart confirmations into flat object
611
+ for (const [key, value] of Object.entries(result.smartConfirmations)) {
612
+ flatCoreInputs[key] = value;
613
+ }
614
+ return {
615
+ ...result,
616
+ flatInputs: flatCoreInputs
617
+ };
603
618
  }
604
619
  }
@@ -3,13 +3,17 @@
3
3
  * Programmatic API for creating services from templates
4
4
  */
5
5
 
6
- import { readFileSync, writeFileSync, mkdirSync, existsSync, cpSync, readdirSync, statSync } from 'fs';
6
+ import { readdirSync, statSync, cpSync, rmSync } from 'fs';
7
7
  import { join, dirname, resolve } from 'path';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { FrameworkConfig } from '../utils/framework-config.js';
10
+ import { FileManager } from '../../bin/shared/utils/file-manager.js';
10
11
  const SERVICE_TYPES = ['data-service', 'auth-service', 'content-service', 'api-gateway', 'generic'];
11
12
  export class ServiceCreator {
12
13
  constructor(options = {}) {
14
+ this.fileManager = new FileManager({
15
+ enableCache: true
16
+ });
13
17
  const templatesDir = (() => {
14
18
  try {
15
19
  return join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'templates');
@@ -80,9 +84,9 @@ export class ServiceCreator {
80
84
 
81
85
  // Check if template exists, fall back to generic if not
82
86
  let actualTemplateDir = templateDir;
83
- if (!existsSync(templateDir)) {
87
+ if (!this.fileManager.exists(templateDir)) {
84
88
  const genericTemplate = join(this.templatesDir, 'generic');
85
- if (existsSync(genericTemplate)) {
89
+ if (this.fileManager.exists(genericTemplate)) {
86
90
  console.log(`⚠️ Template for '${config.type}' not found, using 'generic' template as fallback`);
87
91
  actualTemplateDir = genericTemplate;
88
92
  } else {
@@ -91,10 +95,21 @@ export class ServiceCreator {
91
95
  }
92
96
 
93
97
  // Check if service directory already exists
94
- if (existsSync(serviceDir) && !config.force) {
98
+ if (this.fileManager.exists(serviceDir) && !config.force) {
95
99
  throw new Error(`Service directory already exists: ${serviceDir}. Use force option to overwrite.`);
96
100
  }
97
101
 
102
+ // Create service directory and copy template
103
+ this.fileManager.ensureDir(dirname(serviceDir));
104
+
105
+ // If service directory exists (force mode), remove it first
106
+ if (this.fileManager.exists(serviceDir) && config.force) {
107
+ rmSync(serviceDir, {
108
+ recursive: true,
109
+ force: true
110
+ });
111
+ }
112
+
98
113
  // Copy template to service directory
99
114
  cpSync(actualTemplateDir, serviceDir, {
100
115
  recursive: true
@@ -147,7 +162,7 @@ export class ServiceCreator {
147
162
  const files = this.getAllFiles(dir);
148
163
  for (const file of files) {
149
164
  try {
150
- let content = readFileSync(file, 'utf8');
165
+ let content = this.fileManager.readFile(file, 'utf8');
151
166
  let modified = false;
152
167
  for (const [placeholder, value] of Object.entries(variables)) {
153
168
  if (content.includes(placeholder)) {
@@ -156,7 +171,7 @@ export class ServiceCreator {
156
171
  }
157
172
  }
158
173
  if (modified) {
159
- writeFileSync(file, content, 'utf8');
174
+ this.fileManager.writeFile(file, content, 'utf8');
160
175
  }
161
176
  } catch (error) {
162
177
  // Skip binary files or files that can't be read
@@ -218,7 +233,7 @@ export class ServiceCreator {
218
233
  */
219
234
  getFrameworkVersion() {
220
235
  try {
221
- const packageJson = JSON.parse(readFileSync(join(__dirname, '..', '..', 'package.json'), 'utf8'));
236
+ const packageJson = JSON.parse(this.fileManager.readFile(join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json'), 'utf8'));
222
237
  return packageJson.version;
223
238
  } catch {
224
239
  return '1.0.0';
@@ -3,9 +3,10 @@
3
3
  * Programmatic API for initializing services with configurations
4
4
  */
5
5
 
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync, readdirSync } from 'fs';
6
+ import { readdirSync } from 'fs';
7
7
  import { join, dirname, resolve } from 'path';
8
8
  import { fileURLToPath } from 'url';
9
+ import { FileManager } from '../../bin/shared/utils/file-manager.js';
9
10
 
10
11
  // Get framework root - handle both ES module and CommonJS environments
11
12
  const getFrameworkRoot = () => {
@@ -24,6 +25,9 @@ const TEMPLATES_DIR = join(FRAMEWORK_ROOT, 'templates');
24
25
  const SERVICE_TYPES = ['generic', 'data-service', 'auth-service', 'content-service', 'api-gateway'];
25
26
  export class ServiceInitializer {
26
27
  constructor(options = {}) {
28
+ this.fileManager = new FileManager({
29
+ enableCache: true
30
+ });
27
31
  this.frameworkRoot = options.frameworkRoot || FRAMEWORK_ROOT;
28
32
  this.templatesDir = options.templatesDir || TEMPLATES_DIR;
29
33
  this.serviceTypes = options.serviceTypes || SERVICE_TYPES;
@@ -403,26 +407,16 @@ ${domainInfo.domains.map(d => `- ${d.domain}`).join('\n')}
403
407
  const serviceDir = join(servicesDir, serviceName);
404
408
 
405
409
  // Create directories
406
- mkdirSync(servicesDir, {
407
- recursive: true
408
- });
409
- mkdirSync(serviceDir, {
410
- recursive: true
411
- });
412
- mkdirSync(join(serviceDir, 'src', 'config'), {
413
- recursive: true
414
- });
415
- mkdirSync(join(serviceDir, 'src', 'worker'), {
416
- recursive: true
417
- });
410
+ this.fileManager.ensureDir(servicesDir);
411
+ this.fileManager.ensureDir(serviceDir);
412
+ this.fileManager.ensureDir(join(serviceDir, 'src', 'config'));
413
+ this.fileManager.ensureDir(join(serviceDir, 'src', 'worker'));
418
414
 
419
415
  // Write configuration files
420
416
  for (const [filePath, content] of Object.entries(configs)) {
421
417
  const fullPath = join(serviceDir, filePath);
422
- mkdirSync(dirname(fullPath), {
423
- recursive: true
424
- });
425
- writeFileSync(fullPath, content, 'utf8');
418
+ this.fileManager.ensureDir(dirname(fullPath));
419
+ this.fileManager.writeFile(fullPath, content, 'utf8');
426
420
  }
427
421
 
428
422
  // Create basic worker file
@@ -440,7 +434,7 @@ export default {
440
434
  }
441
435
  };
442
436
  `;
443
- writeFileSync(join(serviceDir, 'src', 'worker', 'index.js'), workerContent, 'utf8');
437
+ this.fileManager.writeFile(join(serviceDir, 'src', 'worker', 'index.js'), workerContent, 'utf8');
444
438
  }
445
439
 
446
440
  /**
@@ -9,6 +9,7 @@
9
9
  import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
10
10
  import { join, dirname } from 'path';
11
11
  import { fileURLToPath } from 'url';
12
+ import { NameFormatters, UrlFormatters, ResourceFormatters, EnvironmentFormatters } from '../utils/Formatters.js';
12
13
  const __filename = fileURLToPath(import.meta.url);
13
14
  const __dirname = dirname(__filename);
14
15
 
@@ -185,7 +186,7 @@ export class DomainDiscovery {
185
186
  const config = {
186
187
  // Basic domain information
187
188
  name: cleanDomainName,
188
- displayName: this.capitalizeFirst(cleanDomainName),
189
+ displayName: NameFormatters.toDisplayName(cleanDomainName),
189
190
  fullDomain: domainName,
190
191
  // Cloudflare infrastructure
191
192
  accountId: account.id,
@@ -204,19 +205,19 @@ export class DomainDiscovery {
204
205
  // Service URLs
205
206
  services: {
206
207
  frontend: {
207
- production: `https://${domainName}`,
208
- staging: `https://staging.${domainName}`,
209
- development: `https://dev.${domainName}`
208
+ production: UrlFormatters.buildProductionUrl('www', domainName),
209
+ staging: UrlFormatters.buildStagingUrl('www', domainName),
210
+ development: UrlFormatters.buildDevUrl('www', domainName)
210
211
  },
211
212
  api: {
212
- production: `https://api.${domainName}`,
213
- staging: `https://api-staging.${domainName}`,
214
- development: `https://api-dev.${domainName}`
213
+ production: UrlFormatters.buildProductionUrl('api', domainName),
214
+ staging: UrlFormatters.buildStagingUrl('api', domainName),
215
+ development: UrlFormatters.buildDevUrl('api', domainName)
215
216
  },
216
217
  auth: {
217
- production: `https://auth.${domainName}`,
218
- staging: `https://auth-staging.${domainName}`,
219
- development: `https://auth-dev.${domainName}`
218
+ production: UrlFormatters.buildProductionUrl('auth', domainName),
219
+ staging: UrlFormatters.buildStagingUrl('auth', domainName),
220
+ development: UrlFormatters.buildDevUrl('auth', domainName)
220
221
  }
221
222
  },
222
223
  // CORS configuration
@@ -8,7 +8,7 @@
8
8
  import { exec } from 'child_process';
9
9
  import { promisify } from 'util';
10
10
  import { executeWithRateLimit } from '../utils/rate-limiter.js';
11
- import { ErrorRecoveryManager } from '../utils/error-recovery.js';
11
+ import { ErrorRecoveryManager } from '../utils/index.js';
12
12
  import { SecureTokenManager } from '../security/secure-token-manager.js';
13
13
  import { ProductionMonitor } from '../monitoring/production-monitor.js';
14
14
  import { DatabaseConnectionManager } from '../database/connection-manager.js';