@tamyla/clodo-framework 1.0.0

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 (130) hide show
  1. package/CHANGELOG.md +564 -0
  2. package/LICENSE +21 -0
  3. package/README.md +1393 -0
  4. package/bin/README.md +71 -0
  5. package/bin/clodo-service.js +416 -0
  6. package/bin/security/security-cli.js +96 -0
  7. package/bin/service-management/README.md +74 -0
  8. package/bin/service-management/create-service.js +129 -0
  9. package/bin/service-management/init-service.js +102 -0
  10. package/bin/service-management/init-service.js.backup +889 -0
  11. package/bin/shared/config/customer-cli.js +293 -0
  12. package/dist/config/ConfigurationManager.js +159 -0
  13. package/dist/config/CustomerConfigCLI.js +220 -0
  14. package/dist/config/FeatureManager.js +426 -0
  15. package/dist/config/customers.js +441 -0
  16. package/dist/config/domains.js +180 -0
  17. package/dist/config/features.js +225 -0
  18. package/dist/config/index.js +6 -0
  19. package/dist/database/database-orchestrator.js +730 -0
  20. package/dist/database/index.js +4 -0
  21. package/dist/deployment/auditor.js +971 -0
  22. package/dist/deployment/index.js +10 -0
  23. package/dist/deployment/rollback-manager.js +523 -0
  24. package/dist/deployment/testers/api-tester.js +80 -0
  25. package/dist/deployment/testers/auth-tester.js +129 -0
  26. package/dist/deployment/testers/core.js +217 -0
  27. package/dist/deployment/testers/database-tester.js +105 -0
  28. package/dist/deployment/testers/index.js +74 -0
  29. package/dist/deployment/testers/load-tester.js +120 -0
  30. package/dist/deployment/testers/performance-tester.js +105 -0
  31. package/dist/deployment/validator.js +558 -0
  32. package/dist/deployment/wrangler-deployer.js +574 -0
  33. package/dist/handlers/GenericRouteHandler.js +532 -0
  34. package/dist/index.js +39 -0
  35. package/dist/migration/MigrationAdapters.js +562 -0
  36. package/dist/modules/ModuleManager.js +668 -0
  37. package/dist/modules/security.js +98 -0
  38. package/dist/orchestration/cross-domain-coordinator.js +1083 -0
  39. package/dist/orchestration/index.js +5 -0
  40. package/dist/orchestration/modules/DeploymentCoordinator.js +258 -0
  41. package/dist/orchestration/modules/DomainResolver.js +196 -0
  42. package/dist/orchestration/modules/StateManager.js +332 -0
  43. package/dist/orchestration/multi-domain-orchestrator.js +255 -0
  44. package/dist/routing/EnhancedRouter.js +158 -0
  45. package/dist/schema/SchemaManager.js +778 -0
  46. package/dist/security/ConfigurationValidator.js +490 -0
  47. package/dist/security/DeploymentManager.js +208 -0
  48. package/dist/security/SecretGenerator.js +142 -0
  49. package/dist/security/SecurityCLI.js +228 -0
  50. package/dist/security/index.js +51 -0
  51. package/dist/security/patterns/environment-rules.js +66 -0
  52. package/dist/security/patterns/insecure-patterns.js +21 -0
  53. package/dist/service-management/ConfirmationEngine.js +411 -0
  54. package/dist/service-management/ErrorTracker.js +294 -0
  55. package/dist/service-management/GenerationEngine.js +3109 -0
  56. package/dist/service-management/InputCollector.js +237 -0
  57. package/dist/service-management/ServiceCreator.js +229 -0
  58. package/dist/service-management/ServiceInitializer.js +448 -0
  59. package/dist/service-management/ServiceOrchestrator.js +638 -0
  60. package/dist/service-management/handlers/ConfigMutator.js +130 -0
  61. package/dist/service-management/handlers/ConfirmationHandler.js +71 -0
  62. package/dist/service-management/handlers/GenerationHandler.js +80 -0
  63. package/dist/service-management/handlers/InputHandler.js +59 -0
  64. package/dist/service-management/handlers/ValidationHandler.js +203 -0
  65. package/dist/service-management/index.js +7 -0
  66. package/dist/services/GenericDataService.js +488 -0
  67. package/dist/shared/cloudflare/domain-discovery.js +562 -0
  68. package/dist/shared/cloudflare/domain-manager.js +912 -0
  69. package/dist/shared/cloudflare/index.js +8 -0
  70. package/dist/shared/cloudflare/ops.js +387 -0
  71. package/dist/shared/config/cache.js +1167 -0
  72. package/dist/shared/config/command-config-manager.js +174 -0
  73. package/dist/shared/config/customer-cli.js +258 -0
  74. package/dist/shared/config/index.js +9 -0
  75. package/dist/shared/config/manager.js +289 -0
  76. package/dist/shared/database/connection-manager.js +338 -0
  77. package/dist/shared/database/index.js +7 -0
  78. package/dist/shared/database/orchestrator.js +632 -0
  79. package/dist/shared/deployment/auditor.js +971 -0
  80. package/dist/shared/deployment/index.js +10 -0
  81. package/dist/shared/deployment/rollback-manager.js +523 -0
  82. package/dist/shared/deployment/validator.js +558 -0
  83. package/dist/shared/index.js +32 -0
  84. package/dist/shared/monitoring/health-checker.js +250 -0
  85. package/dist/shared/monitoring/index.js +8 -0
  86. package/dist/shared/monitoring/memory-manager.js +382 -0
  87. package/dist/shared/monitoring/production-monitor.js +390 -0
  88. package/dist/shared/production-tester/api-tester.js +80 -0
  89. package/dist/shared/production-tester/auth-tester.js +129 -0
  90. package/dist/shared/production-tester/core.js +217 -0
  91. package/dist/shared/production-tester/database-tester.js +105 -0
  92. package/dist/shared/production-tester/index.js +74 -0
  93. package/dist/shared/production-tester/load-tester.js +120 -0
  94. package/dist/shared/production-tester/performance-tester.js +105 -0
  95. package/dist/shared/security/api-token-manager.js +296 -0
  96. package/dist/shared/security/index.js +8 -0
  97. package/dist/shared/security/secret-generator.js +918 -0
  98. package/dist/shared/security/secure-token-manager.js +379 -0
  99. package/dist/shared/utils/error-recovery.js +240 -0
  100. package/dist/shared/utils/graceful-shutdown-manager.js +380 -0
  101. package/dist/shared/utils/index.js +9 -0
  102. package/dist/shared/utils/interactive-prompts.js +134 -0
  103. package/dist/shared/utils/rate-limiter.js +249 -0
  104. package/dist/utils/ErrorHandler.js +173 -0
  105. package/dist/utils/deployment/config-cache.js +1160 -0
  106. package/dist/utils/deployment/index.js +6 -0
  107. package/dist/utils/deployment/interactive-prompts.js +97 -0
  108. package/dist/utils/deployment/secret-generator.js +896 -0
  109. package/dist/utils/dirname-helper.js +35 -0
  110. package/dist/utils/domain-config.js +159 -0
  111. package/dist/utils/error-recovery.js +240 -0
  112. package/dist/utils/esm-helper.js +52 -0
  113. package/dist/utils/framework-config.js +481 -0
  114. package/dist/utils/graceful-shutdown-manager.js +379 -0
  115. package/dist/utils/health-checker.js +114 -0
  116. package/dist/utils/index.js +36 -0
  117. package/dist/utils/prompt-handler.js +98 -0
  118. package/dist/utils/usage-tracker.js +252 -0
  119. package/dist/utils/validation.js +112 -0
  120. package/dist/version/VersionDetector.js +723 -0
  121. package/dist/worker/index.js +4 -0
  122. package/dist/worker/integration.js +332 -0
  123. package/docs/FRAMEWORK-ARCHITECTURE-OVERVIEW.md +206 -0
  124. package/docs/INTEGRATION_GUIDE.md +2045 -0
  125. package/docs/README.md +82 -0
  126. package/docs/SECURITY.md +242 -0
  127. package/docs/deployment/deployment-guide.md +540 -0
  128. package/docs/overview.md +280 -0
  129. package/package.json +176 -0
  130. package/types/index.d.ts +575 -0
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Configuration Mutator Module
3
+ * Focused module for safe configuration file mutations
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ export class ConfigMutator {
9
+ constructor(options = {}) {
10
+ this.dryRun = options.dryRun || false;
11
+ }
12
+
13
+ /**
14
+ * Safely update domain configuration
15
+ */
16
+ async updateDomainConfig(servicePath, currentConfig, updates) {
17
+ const domainConfigPath = path.join(servicePath, 'src/config/domains.js');
18
+ let domainConfig = await fs.readFile(domainConfigPath, 'utf8');
19
+ if (updates.domainName) {
20
+ // Use regex-based replacement for safety
21
+ domainConfig = domainConfig.replace(new RegExp(`name: ['"]${this.escapeRegExp(currentConfig.domainName)}['"]`, 'g'), `name: '${updates.domainName}'`);
22
+
23
+ // Update domain URLs
24
+ domainConfig = domainConfig.replace(new RegExp(`https://[^'"]*${this.escapeRegExp(currentConfig.domainName)}[^'"]*`, 'g'), match => match.replace(currentConfig.domainName, updates.domainName));
25
+ }
26
+ if (!this.dryRun) {
27
+ await fs.writeFile(domainConfigPath, domainConfig, 'utf8');
28
+ }
29
+ return {
30
+ updated: true,
31
+ path: domainConfigPath
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Update Cloudflare configuration
37
+ */
38
+ async updateCloudflareConfig(servicePath, currentConfig, updates) {
39
+ const domainConfigPath = path.join(servicePath, 'src/config/domains.js');
40
+ let domainConfig = await fs.readFile(domainConfigPath, 'utf8');
41
+ if (updates.accountId) {
42
+ domainConfig = domainConfig.replace(new RegExp(`accountId:\\s*['"]${this.escapeRegExp(currentConfig.cloudflareAccountId || '')}['"]`, 'g'), `accountId: '${updates.accountId}'`);
43
+ }
44
+ if (updates.zoneId) {
45
+ domainConfig = domainConfig.replace(new RegExp(`zoneId:\\s*['"]${this.escapeRegExp(currentConfig.cloudflareZoneId || '')}['"]`, 'g'), `zoneId: '${updates.zoneId}'`);
46
+ }
47
+ if (!this.dryRun) {
48
+ await fs.writeFile(domainConfigPath, domainConfig, 'utf8');
49
+ }
50
+ return {
51
+ updated: true,
52
+ path: domainConfigPath
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Update environment configuration
58
+ */
59
+ async updateEnvironmentConfig(servicePath, currentConfig, updates) {
60
+ const wranglerConfigPath = path.join(servicePath, 'wrangler.toml');
61
+ let wranglerConfig = await fs.readFile(wranglerConfigPath, 'utf8');
62
+ if (updates.environment) {
63
+ // Update environment-specific names
64
+ wranglerConfig = wranglerConfig.replace(new RegExp(`name\\s*=\\s*['"].*${this.escapeRegExp(currentConfig.environment)}.*['"]`, 'g'), `name = "${currentConfig.serviceName}-${updates.environment}"`);
65
+ wranglerConfig = wranglerConfig.replace(new RegExp(`\\[env\\.${this.escapeRegExp(currentConfig.environment)}\\]`, 'g'), `[env.${updates.environment}]`);
66
+ }
67
+ if (!this.dryRun) {
68
+ await fs.writeFile(wranglerConfigPath, wranglerConfig, 'utf8');
69
+ }
70
+ return {
71
+ updated: true,
72
+ path: wranglerConfigPath
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Update feature configuration
78
+ */
79
+ async updateFeatureConfig(servicePath, action, feature) {
80
+ const domainConfigPath = path.join(servicePath, 'src/config/domains.js');
81
+ let domainConfig = await fs.readFile(domainConfigPath, 'utf8');
82
+ if (action === 'add') {
83
+ // Add feature flag
84
+ const featureLine = ` ${feature}: true,`;
85
+ domainConfig = domainConfig.replace(/(\s+)(cors:\s*(?:true|false),?)(\n)/, `$1$2$3$1${featureLine}$3`);
86
+ } else if (action === 'remove') {
87
+ // Remove feature flag
88
+ const featureLinePattern = new RegExp(`\\s+${this.escapeRegExp(feature)}:\\s*(?:true|false),?\\n`, 'g');
89
+ domainConfig = domainConfig.replace(featureLinePattern, '');
90
+ }
91
+ if (!this.dryRun) {
92
+ await fs.writeFile(domainConfigPath, domainConfig, 'utf8');
93
+ }
94
+ return {
95
+ updated: true,
96
+ path: domainConfigPath
97
+ };
98
+ }
99
+
100
+ /**
101
+ * Validate configuration file exists and is writable
102
+ */
103
+ async validateConfigFile(filePath) {
104
+ try {
105
+ await fs.access(filePath, fs.constants.R_OK | fs.constants.W_OK);
106
+ return {
107
+ valid: true
108
+ };
109
+ } catch (error) {
110
+ return {
111
+ valid: false,
112
+ error: `Configuration file not accessible: ${filePath}`
113
+ };
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Escape special regex characters for safe replacement
119
+ */
120
+ escapeRegExp(string) {
121
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
122
+ }
123
+
124
+ /**
125
+ * Enable/disable dry run mode
126
+ */
127
+ setDryRun(enabled) {
128
+ this.dryRun = enabled;
129
+ }
130
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Confirmation Handler Module
3
+ * Focused module for handling smart confirmations and derived values
4
+ */
5
+
6
+ import { ConfirmationEngine } from '../ConfirmationEngine.js';
7
+ import { createPromptHandler } from '../../utils/prompt-handler.js';
8
+ export class ConfirmationHandler {
9
+ constructor(options = {}) {
10
+ this.interactive = options.interactive !== false;
11
+ this.promptHandler = createPromptHandler({
12
+ interactive: this.interactive
13
+ });
14
+ this.confirmationEngine = new ConfirmationEngine({
15
+ interactive: this.interactive
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Generate and confirm derived values from core inputs
21
+ */
22
+ async generateAndConfirm(coreInputs) {
23
+ return await this.confirmationEngine.generateAndConfirm(coreInputs);
24
+ }
25
+
26
+ /**
27
+ * Generate smart defaults without interaction
28
+ */
29
+ generateSmartDefaults(coreInputs) {
30
+ return this.confirmationEngine.generateSmartDefaults(coreInputs);
31
+ }
32
+
33
+ /**
34
+ * Interactive confirmation of specific values
35
+ */
36
+ async confirmValue(field, currentValue, question) {
37
+ if (!this.interactive) {
38
+ return currentValue;
39
+ }
40
+ const confirmed = await this.promptHandler.confirm(`${question}\nCurrent value: ${currentValue}\nKeep this value?`, true);
41
+ if (!confirmed) {
42
+ return await this.promptHandler.prompt('Enter new value: ');
43
+ }
44
+ return currentValue;
45
+ }
46
+
47
+ /**
48
+ * Confirm entire configuration
49
+ */
50
+ async confirmConfiguration(config) {
51
+ if (!this.interactive) {
52
+ return true;
53
+ }
54
+ console.log('\n📋 Configuration Summary:');
55
+ Object.entries(config).forEach(([key, value]) => {
56
+ // Mask sensitive values
57
+ if (key.toLowerCase().includes('token') || key.toLowerCase().includes('secret')) {
58
+ value = '*'.repeat(8) + value.slice(-4);
59
+ }
60
+ console.log(` ${key}: ${value}`);
61
+ });
62
+ return await this.promptHandler.confirm('\nProceed with this configuration?', true);
63
+ }
64
+
65
+ /**
66
+ * Cleanup resources
67
+ */
68
+ async cleanup() {
69
+ await this.promptHandler.close();
70
+ }
71
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Generation Handler Module
3
+ * Focused module for service generation and file creation
4
+ */
5
+
6
+ import { GenerationEngine } from '../GenerationEngine.js';
7
+ export class GenerationHandler {
8
+ constructor(options = {}) {
9
+ this.outputPath = options.outputPath || '.';
10
+ this.templatePath = options.templatePath || './templates';
11
+ this.generationEngine = new GenerationEngine({
12
+ outputDir: this.outputPath,
13
+ templatesDir: this.templatePath
14
+ });
15
+ }
16
+
17
+ /**
18
+ * Generate complete service from inputs and confirmed values
19
+ */
20
+ async generateService(coreInputs, confirmedValues, options = {}) {
21
+ const config = {
22
+ outputPath: this.outputPath,
23
+ ...options
24
+ };
25
+ return await this.generationEngine.generateService(coreInputs, confirmedValues, config);
26
+ }
27
+
28
+ /**
29
+ * Generate specific component
30
+ */
31
+ async generateComponent(componentType, config, outputPath) {
32
+ // Delegate to generation engine's specific methods
33
+ switch (componentType) {
34
+ case 'manifest':
35
+ return this.generationEngine.createServiceManifest(config.coreInputs, config.confirmedValues, config.generatedFiles || []);
36
+ case 'directory':
37
+ return this.generationEngine.createDirectoryStructure(outputPath);
38
+ default:
39
+ throw new Error(`Unknown component type: ${componentType}`);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Validate generation prerequisites
45
+ */
46
+ async validatePrerequisites(coreInputs, confirmedValues) {
47
+ const issues = [];
48
+
49
+ // Check required inputs
50
+ if (!coreInputs.serviceName) {
51
+ issues.push('Service name is required');
52
+ }
53
+ if (!coreInputs.serviceType) {
54
+ issues.push('Service type is required');
55
+ }
56
+
57
+ // Check output path permissions
58
+ try {
59
+ const fs = await import('fs/promises');
60
+ await fs.access(this.outputPath);
61
+ } catch (error) {
62
+ issues.push(`Output path not accessible: ${this.outputPath}`);
63
+ }
64
+ return {
65
+ valid: issues.length === 0,
66
+ issues
67
+ };
68
+ }
69
+
70
+ /**
71
+ * Get generation progress information
72
+ */
73
+ getGenerationStatus() {
74
+ return {
75
+ outputPath: this.outputPath,
76
+ templatePath: this.templatePath,
77
+ ready: true
78
+ };
79
+ }
80
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Input Handler Module
3
+ * Focused module for collecting core service inputs
4
+ */
5
+
6
+ import { InputCollector } from '../InputCollector.js';
7
+ import { createPromptHandler } from '../../utils/prompt-handler.js';
8
+ export class InputHandler {
9
+ constructor(options = {}) {
10
+ this.interactive = options.interactive !== false;
11
+ this.promptHandler = createPromptHandler({
12
+ interactive: this.interactive
13
+ });
14
+ this.inputCollector = new InputCollector({
15
+ interactive: this.interactive
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Collect the 6 core inputs required for service creation
21
+ */
22
+ async collectCoreInputs() {
23
+ return await this.inputCollector.collectCoreInputs();
24
+ }
25
+
26
+ /**
27
+ * Validate core inputs without prompting
28
+ */
29
+ async validateCoreInputs(inputs) {
30
+ return await this.inputCollector.validateCoreInputs(inputs);
31
+ }
32
+
33
+ /**
34
+ * Interactive input collection with custom prompts
35
+ */
36
+ async promptForInput(field, question, defaultValue = '', required = false) {
37
+ if (!this.interactive) {
38
+ return defaultValue;
39
+ }
40
+ let answer;
41
+ do {
42
+ answer = await this.promptHandler.prompt(question);
43
+ if (!answer && defaultValue) {
44
+ answer = defaultValue;
45
+ }
46
+ if (required && !answer) {
47
+ console.log('This field is required. Please provide a value.');
48
+ }
49
+ } while (required && !answer);
50
+ return answer;
51
+ }
52
+
53
+ /**
54
+ * Cleanup resources
55
+ */
56
+ async cleanup() {
57
+ await this.promptHandler.close();
58
+ }
59
+ }
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Validation Handler Module
3
+ * Focused module for service validation and health checks
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import path from 'path';
8
+ export class ValidationHandler {
9
+ constructor(options = {}) {
10
+ this.strict = options.strict || false;
11
+ }
12
+
13
+ /**
14
+ * Validate complete service configuration
15
+ */
16
+ async validateService(servicePath) {
17
+ const issues = [];
18
+
19
+ // Check for required files
20
+ const requiredFiles = ['package.json', 'src/config/domains.js', 'src/worker/index.js', 'wrangler.toml'];
21
+ for (const file of requiredFiles) {
22
+ const filePath = path.join(servicePath, file);
23
+ try {
24
+ await fs.access(filePath);
25
+ } catch {
26
+ issues.push(`Missing required file: ${file}`);
27
+ }
28
+ }
29
+
30
+ // Validate package.json
31
+ const packageValidation = await this.validatePackageJson(servicePath);
32
+ issues.push(...packageValidation.issues);
33
+
34
+ // Validate domain configuration
35
+ const domainValidation = await this.validateDomainConfig(servicePath);
36
+ issues.push(...domainValidation.issues);
37
+
38
+ // Validate wrangler configuration
39
+ const wranglerValidation = await this.validateWranglerConfig(servicePath);
40
+ issues.push(...wranglerValidation.issues);
41
+ return {
42
+ valid: issues.length === 0,
43
+ issues,
44
+ servicePath
45
+ };
46
+ }
47
+
48
+ /**
49
+ * Validate package.json structure
50
+ */
51
+ async validatePackageJson(servicePath) {
52
+ const issues = [];
53
+ const packageJsonPath = path.join(servicePath, 'package.json');
54
+ try {
55
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
56
+ if (!packageJson.name) {
57
+ issues.push('package.json: Missing name field');
58
+ }
59
+ if (!packageJson.version) {
60
+ issues.push('package.json: Missing version field');
61
+ }
62
+ if (!packageJson.type || packageJson.type !== 'module') {
63
+ issues.push('package.json: Should use "type": "module" for ES modules');
64
+ }
65
+
66
+ // Check for required dependencies
67
+ const requiredDeps = ['@tamyla/clodo-framework'];
68
+ const deps = {
69
+ ...packageJson.dependencies,
70
+ ...packageJson.devDependencies
71
+ };
72
+ requiredDeps.forEach(dep => {
73
+ if (!deps[dep]) {
74
+ issues.push(`package.json: Missing required dependency: ${dep}`);
75
+ }
76
+ });
77
+ } catch (error) {
78
+ issues.push(`package.json: Invalid JSON format - ${error.message}`);
79
+ }
80
+ return {
81
+ issues
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Validate domain configuration
87
+ */
88
+ async validateDomainConfig(servicePath) {
89
+ const issues = [];
90
+ const domainConfigPath = path.join(servicePath, 'src/config/domains.js');
91
+ try {
92
+ const domainConfig = await fs.readFile(domainConfigPath, 'utf8');
93
+
94
+ // Check for Clodo Framework integration
95
+ if (!domainConfig.includes('createDomainConfigSchema')) {
96
+ issues.push('Domain configuration missing Clodo Framework integration');
97
+ }
98
+
99
+ // Check for required exports
100
+ if (!domainConfig.includes('export const domains')) {
101
+ issues.push('Domain configuration missing domains export');
102
+ }
103
+
104
+ // Basic domain format validation
105
+ const domainMatches = domainConfig.match(/domain:\s*['"]([^'"]+)['"]/g);
106
+ if (domainMatches) {
107
+ domainMatches.forEach(match => {
108
+ const domain = match.match(/domain:\s*['"]([^'"]+)['"]/)[1];
109
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.[a-zA-Z]{2,}$/.test(domain)) {
110
+ issues.push(`Invalid domain format: ${domain}`);
111
+ }
112
+ });
113
+ }
114
+ } catch (error) {
115
+ issues.push(`Domain configuration: Cannot read file - ${error.message}`);
116
+ }
117
+ return {
118
+ issues
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Validate wrangler configuration
124
+ */
125
+ async validateWranglerConfig(servicePath) {
126
+ const issues = [];
127
+ const wranglerConfigPath = path.join(servicePath, 'wrangler.toml');
128
+ try {
129
+ const wranglerConfig = await fs.readFile(wranglerConfigPath, 'utf8');
130
+
131
+ // Check for required fields
132
+ if (!wranglerConfig.includes('name =')) {
133
+ issues.push('wrangler.toml: Missing name field');
134
+ }
135
+ if (!wranglerConfig.includes('main =')) {
136
+ issues.push('wrangler.toml: Missing main field');
137
+ }
138
+ if (!wranglerConfig.includes('compatibility_date =')) {
139
+ issues.push('wrangler.toml: Missing compatibility_date');
140
+ }
141
+ } catch (error) {
142
+ issues.push(`wrangler.toml: Cannot read file - ${error.message}`);
143
+ }
144
+ return {
145
+ issues
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Run comprehensive service diagnostics
151
+ */
152
+ async diagnoseService(servicePath) {
153
+ const diagnosis = {
154
+ errors: [],
155
+ warnings: [],
156
+ recommendations: []
157
+ };
158
+
159
+ // Basic validation
160
+ const validation = await this.validateService(servicePath);
161
+ validation.issues.forEach(issue => {
162
+ if (issue.includes('Missing required')) {
163
+ diagnosis.errors.push({
164
+ message: issue,
165
+ severity: 'high',
166
+ suggestion: 'Run service initialization to create missing files'
167
+ });
168
+ } else if (issue.includes('Invalid')) {
169
+ diagnosis.errors.push({
170
+ message: issue,
171
+ severity: 'medium',
172
+ suggestion: 'Review and correct the configuration'
173
+ });
174
+ } else {
175
+ diagnosis.warnings.push({
176
+ message: issue,
177
+ suggestion: 'Consider updating for better compatibility'
178
+ });
179
+ }
180
+ });
181
+
182
+ // Additional recommendations
183
+ try {
184
+ const packageJson = JSON.parse(await fs.readFile(path.join(servicePath, 'package.json'), 'utf8'));
185
+ if (!packageJson.scripts || !packageJson.scripts.dev) {
186
+ diagnosis.recommendations.push('Add development scripts for easier testing');
187
+ }
188
+ if (!packageJson.scripts || !packageJson.scripts.deploy) {
189
+ diagnosis.recommendations.push('Add deployment scripts for easier publishing');
190
+ }
191
+ } catch (error) {
192
+ // Package.json validation already handled above
193
+ }
194
+ return diagnosis;
195
+ }
196
+
197
+ /**
198
+ * Set validation strictness
199
+ */
200
+ setStrict(enabled) {
201
+ this.strict = enabled;
202
+ }
203
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Clodo Framework - Service Management Module
3
+ * Programmatic APIs for service creation and initialization
4
+ */
5
+
6
+ export { ServiceCreator, createService } from './ServiceCreator.js';
7
+ export { ServiceInitializer, initializeService } from './ServiceInitializer.js';