@tamyla/clodo-framework 3.0.11 → 3.0.13
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.
- package/CHANGELOG.md +16 -0
- package/bin/clodo-service.js +385 -184
- package/dist/orchestration/multi-domain-orchestrator.js +131 -63
- package/dist/service-management/AssessmentCache.js +303 -0
- package/dist/service-management/CapabilityAssessmentEngine.js +902 -0
- package/dist/service-management/ConfirmationEngine.js +4 -4
- package/dist/service-management/InputCollector.js +119 -4
- package/dist/service-management/ServiceAutoDiscovery.js +745 -0
- package/dist/service-management/ServiceCreator.js +1 -4
- package/dist/service-management/ServiceOrchestrator.js +269 -1
- package/dist/service-management/index.js +4 -1
- package/dist/utils/cloudflare/api.js +41 -1
- package/dist/utils/config/unified-config-manager.js +6 -2
- package/dist/utils/deployment/wrangler-config-manager.js +32 -7
- package/package.json +1 -1
- package/templates/generic/src/config/domains.js +3 -3
|
@@ -81,10 +81,10 @@ export class ConfirmationEngine {
|
|
|
81
81
|
version: '1.0.0',
|
|
82
82
|
// 4. Author - Default framework author
|
|
83
83
|
author: 'Clodo Framework',
|
|
84
|
-
// 5-7. URLs - Derived from domain
|
|
85
|
-
productionUrl: `https
|
|
86
|
-
stagingUrl: `https
|
|
87
|
-
developmentUrl: `https
|
|
84
|
+
// 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}`,
|
|
88
88
|
// 8. Features - Based on service type
|
|
89
89
|
features: this.generateFeaturesForType(serviceType),
|
|
90
90
|
// 9. Database Name - Cloudflare D1 naming
|
|
@@ -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 { CapabilityAssessmentEngine } from './CapabilityAssessmentEngine.js';
|
|
18
19
|
export class InputCollector {
|
|
19
20
|
constructor(options = {}) {
|
|
20
21
|
this.interactive = options.interactive !== false;
|
|
@@ -80,6 +81,11 @@ export class InputCollector {
|
|
|
80
81
|
source: 'user-provided',
|
|
81
82
|
required: true
|
|
82
83
|
};
|
|
84
|
+
|
|
85
|
+
// Run assessment after API token is collected
|
|
86
|
+
if (inputDef.id === 'cloudflare-api-token' && value) {
|
|
87
|
+
await this.runDeploymentReadinessAssessment(result.coreInputs);
|
|
88
|
+
}
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -158,9 +164,9 @@ export class InputCollector {
|
|
|
158
164
|
case 'production-url':
|
|
159
165
|
return domainName ? `https://api.${domainName}` : '';
|
|
160
166
|
case 'staging-url':
|
|
161
|
-
return domainName ? `https
|
|
167
|
+
return domainName && serviceName ? `https://${serviceName}-staging.${domainName}` : '';
|
|
162
168
|
case 'development-url':
|
|
163
|
-
return domainName ? `https
|
|
169
|
+
return domainName && serviceName ? `https://${serviceName}-dev.${domainName}` : '';
|
|
164
170
|
case 'service-directory':
|
|
165
171
|
return serviceName ? `./services/${serviceName}` : '';
|
|
166
172
|
case 'database-name':
|
|
@@ -386,8 +392,25 @@ export class InputCollector {
|
|
|
386
392
|
CloudflareAPI
|
|
387
393
|
} = await import('../utils/cloudflare/api.js');
|
|
388
394
|
const cfApi = new CloudflareAPI(token);
|
|
389
|
-
const
|
|
390
|
-
if (
|
|
395
|
+
const tokenCheck = await cfApi.verifyToken();
|
|
396
|
+
if (tokenCheck.valid) {
|
|
397
|
+
// Check D1 permissions
|
|
398
|
+
const permissionCheck = await cfApi.checkD1Permissions();
|
|
399
|
+
if (!permissionCheck.hasPermission) {
|
|
400
|
+
console.log(chalk.yellow(`⚠️ ${permissionCheck.error}`));
|
|
401
|
+
console.log(chalk.white(' 💡 You can update permissions at: https://dash.cloudflare.com/profile/api-tokens'));
|
|
402
|
+
console.log(chalk.white(' 💡 Or continue and the framework will fall back to OAuth authentication'));
|
|
403
|
+
console.log('');
|
|
404
|
+
const {
|
|
405
|
+
askYesNo
|
|
406
|
+
} = await import('../utils/interactive-prompts.js');
|
|
407
|
+
const continueAnyway = await askYesNo('Continue with limited API token permissions?', false);
|
|
408
|
+
if (!continueAnyway) {
|
|
409
|
+
console.log(chalk.blue('Please update your API token permissions and try again.'));
|
|
410
|
+
process.exit(0);
|
|
411
|
+
}
|
|
412
|
+
console.log(chalk.yellow('⚠️ Proceeding with limited permissions - database operations will use OAuth'));
|
|
413
|
+
}
|
|
391
414
|
console.log(chalk.green('✓ API token verified successfully'));
|
|
392
415
|
return token;
|
|
393
416
|
}
|
|
@@ -556,6 +579,98 @@ export class InputCollector {
|
|
|
556
579
|
});
|
|
557
580
|
}
|
|
558
581
|
|
|
582
|
+
/**
|
|
583
|
+
* Run deployment readiness assessment after API token collection
|
|
584
|
+
*/
|
|
585
|
+
async runDeploymentReadinessAssessment(coreInputs) {
|
|
586
|
+
console.log(chalk.cyan('\n🔍 Running Deployment Readiness Assessment...'));
|
|
587
|
+
console.log(chalk.gray('Analyzing your inputs for deployment feasibility...\n'));
|
|
588
|
+
try {
|
|
589
|
+
// Convert core inputs to assessment format
|
|
590
|
+
const assessmentInputs = {
|
|
591
|
+
serviceName: coreInputs['service-name']?.value,
|
|
592
|
+
serviceType: coreInputs['service-type']?.value || 'generic',
|
|
593
|
+
domainName: coreInputs['domain-name']?.value,
|
|
594
|
+
environment: coreInputs['environment']?.value || 'development',
|
|
595
|
+
cloudflareToken: coreInputs['cloudflare-api-token']?.value,
|
|
596
|
+
customerName: coreInputs['customer-name']?.value
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
// Create assessment engine with caching enabled
|
|
600
|
+
const assessmentEngine = new CapabilityAssessmentEngine(process.cwd(), {
|
|
601
|
+
cacheEnabled: true,
|
|
602
|
+
cache: {
|
|
603
|
+
ttl: 10 * 60 * 1000
|
|
604
|
+
} // 10 minutes for interactive sessions
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
// Run assessment
|
|
608
|
+
const assessment = await assessmentEngine.assessCapabilities(assessmentInputs);
|
|
609
|
+
|
|
610
|
+
// Display results
|
|
611
|
+
this.displayAssessmentResults(assessment);
|
|
612
|
+
|
|
613
|
+
// Store assessment in result for later use
|
|
614
|
+
return assessment;
|
|
615
|
+
} catch (error) {
|
|
616
|
+
console.log(chalk.yellow(`⚠️ Assessment failed: ${error.message}`));
|
|
617
|
+
console.log(chalk.gray('Continuing with service creation...'));
|
|
618
|
+
return null;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Display assessment results in user-friendly format
|
|
624
|
+
*/
|
|
625
|
+
displayAssessmentResults(assessment) {
|
|
626
|
+
const {
|
|
627
|
+
capabilityManifest,
|
|
628
|
+
gapAnalysis,
|
|
629
|
+
confidence,
|
|
630
|
+
cached
|
|
631
|
+
} = assessment;
|
|
632
|
+
console.log(chalk.cyan('\n📊 Assessment Results:'));
|
|
633
|
+
console.log(chalk.gray('─'.repeat(40)));
|
|
634
|
+
|
|
635
|
+
// Service type and confidence
|
|
636
|
+
console.log(chalk.white(`Service Type: ${capabilityManifest.serviceType}`));
|
|
637
|
+
console.log(chalk.white(`Confidence: ${confidence.toFixed(1)}%`));
|
|
638
|
+
if (cached) {
|
|
639
|
+
console.log(chalk.gray('(Results loaded from cache)'));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Gap analysis summary
|
|
643
|
+
const missingCount = gapAnalysis.missing.length;
|
|
644
|
+
const blockedCount = gapAnalysis.missing.filter(gap => gap.priority === 'blocked').length;
|
|
645
|
+
if (missingCount === 0) {
|
|
646
|
+
console.log(chalk.green('✅ All required capabilities detected'));
|
|
647
|
+
} else {
|
|
648
|
+
console.log(chalk.yellow(`⚠️ ${missingCount} capability gap(s) found`));
|
|
649
|
+
if (blockedCount > 0) {
|
|
650
|
+
console.log(chalk.red(`🚫 ${blockedCount} deployment blocker(s) detected`));
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Show top 3 gaps
|
|
654
|
+
gapAnalysis.missing.slice(0, 3).forEach(gap => {
|
|
655
|
+
const icon = gap.priority === 'blocked' ? '🚫' : '⚠️';
|
|
656
|
+
console.log(chalk.gray(` ${icon} ${gap.capability}: ${gap.reason}`));
|
|
657
|
+
});
|
|
658
|
+
if (gapAnalysis.missing.length > 3) {
|
|
659
|
+
console.log(chalk.gray(` ... and ${gapAnalysis.missing.length - 3} more`));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Recommendations
|
|
664
|
+
if (assessment.recommendations && assessment.recommendations.length > 0) {
|
|
665
|
+
console.log(chalk.blue('\n💡 Recommendations:'));
|
|
666
|
+
assessment.recommendations.slice(0, 2).forEach(rec => {
|
|
667
|
+
console.log(chalk.gray(` • ${rec.message}`));
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
console.log(chalk.gray('\n─'.repeat(40)));
|
|
671
|
+
console.log(chalk.white('Continue with service creation? (Assessment will run again before generation)'));
|
|
672
|
+
}
|
|
673
|
+
|
|
559
674
|
/**
|
|
560
675
|
* Close readline interface and clean up
|
|
561
676
|
*/
|