@vee-stack/delta-cli 2.0.4 → 2.0.6
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/dist/analyzer/commands/analyze.js +260 -0
- package/dist/analyzer/commands/config.js +83 -0
- package/dist/analyzer/commands/report.js +38 -0
- package/dist/analyzer/generators/report.generator.js +123 -0
- package/dist/analyzer/index.js +44 -0
- package/dist/analyzer/scanners/project.scanner.js +92 -0
- package/dist/analyzer/validators/contracts.validator.js +42 -0
- package/dist/analyzer/validators/maintainability.validator.js +40 -0
- package/dist/analyzer/validators/observability.validator.js +39 -0
- package/dist/analyzer/validators/performance.validator.js +42 -0
- package/dist/analyzer/validators/security.validator.js +66 -0
- package/dist/analyzer/validators/soc.validator.js +75 -0
- package/dist/apps/cli/src/analyzer/commands/analyze.js +256 -0
- package/dist/apps/cli/src/analyzer/commands/config.js +83 -0
- package/dist/apps/cli/src/analyzer/commands/report.js +38 -0
- package/dist/apps/cli/src/analyzer/generators/report.generator.js +123 -0
- package/dist/apps/cli/src/analyzer/index.js +44 -0
- package/dist/apps/cli/src/analyzer/scanners/project.scanner.js +92 -0
- package/dist/apps/cli/src/analyzer/validators/contracts.validator.js +42 -0
- package/dist/apps/cli/src/analyzer/validators/maintainability.validator.js +40 -0
- package/dist/apps/cli/src/analyzer/validators/observability.validator.js +39 -0
- package/dist/apps/cli/src/analyzer/validators/performance.validator.js +42 -0
- package/dist/apps/cli/src/analyzer/validators/security.validator.js +66 -0
- package/dist/apps/cli/src/analyzer/validators/soc.validator.js +75 -0
- package/dist/apps/cli/src/auth/secure-auth.js +312 -0
- package/dist/apps/cli/src/commands/analyze.js +286 -0
- package/dist/apps/cli/src/commands/auth-new.js +37 -0
- package/dist/apps/cli/src/commands/auth.js +122 -0
- package/dist/apps/cli/src/commands/config.js +49 -0
- package/dist/apps/cli/src/commands/deploy.js +6 -0
- package/dist/apps/cli/src/commands/init.js +47 -0
- package/dist/apps/cli/src/commands/logout.js +23 -0
- package/dist/apps/cli/src/commands/plugins.js +21 -0
- package/dist/apps/cli/src/commands/status.js +80 -0
- package/dist/apps/cli/src/commands/sync.js +6 -0
- package/dist/apps/cli/src/commands/whoami.js +115 -0
- package/dist/apps/cli/src/components/Dashboard.js +168 -0
- package/dist/apps/cli/src/components/DeltaApp.js +56 -0
- package/dist/apps/cli/src/components/UnifiedManager.js +324 -0
- package/dist/apps/cli/src/core/audit.js +184 -0
- package/dist/apps/cli/src/core/completion.js +294 -0
- package/dist/apps/cli/src/core/contracts.js +6 -0
- package/dist/apps/cli/src/core/engine.js +124 -0
- package/dist/apps/cli/src/core/exit-codes.js +71 -0
- package/dist/apps/cli/src/core/hooks.js +181 -0
- package/dist/apps/cli/src/core/index.js +7 -0
- package/dist/apps/cli/src/core/policy.js +115 -0
- package/dist/apps/cli/src/core/profiles.js +161 -0
- package/dist/apps/cli/src/core/wizard.js +203 -0
- package/dist/apps/cli/src/index.js +636 -0
- package/dist/apps/cli/src/interactive/index.js +11 -0
- package/dist/apps/cli/src/plugins/GitStatusPlugin.js +99 -0
- package/dist/apps/cli/src/providers/ai-provider.js +74 -0
- package/dist/apps/cli/src/providers/local-provider.js +302 -0
- package/dist/apps/cli/src/providers/remote-provider.js +100 -0
- package/dist/apps/cli/src/types/api.js +3 -0
- package/dist/apps/cli/src/ui.js +219 -0
- package/dist/apps/cli/src/welcome.js +81 -0
- package/dist/auth/secure-auth.js +418 -0
- package/dist/bundle.js +45 -45
- package/dist/commands/analyze.js +384 -0
- package/dist/commands/auth-new.js +37 -0
- package/dist/commands/auth.js +134 -0
- package/dist/commands/config.js +51 -0
- package/dist/commands/deploy.js +6 -0
- package/dist/commands/init.js +47 -0
- package/dist/commands/logout.js +31 -0
- package/dist/commands/plugins.js +21 -0
- package/dist/commands/status.js +82 -0
- package/dist/commands/sync.js +6 -0
- package/dist/commands/whoami.js +72 -0
- package/dist/components/Dashboard.js +169 -0
- package/dist/components/DeltaApp.js +57 -0
- package/dist/components/UnifiedManager.js +344 -0
- package/dist/core/audit.js +184 -0
- package/dist/core/completion.js +294 -0
- package/dist/core/contracts.js +6 -0
- package/dist/core/engine.js +124 -0
- package/dist/core/exit-codes.js +71 -0
- package/dist/core/hooks.js +181 -0
- package/dist/core/index.js +7 -0
- package/dist/core/policy.js +115 -0
- package/dist/core/profiles.js +161 -0
- package/dist/core/wizard.js +203 -0
- package/dist/index.js +387 -0
- package/dist/interactive/index.js +11 -0
- package/dist/packages/domain/src/constitution/contracts/index.js +43 -0
- package/dist/packages/domain/src/constitution/contracts/ts.rules.js +268 -0
- package/dist/packages/domain/src/constitution/index.js +139 -0
- package/dist/packages/domain/src/constitution/maintainability/index.js +43 -0
- package/dist/packages/domain/src/constitution/maintainability/ts.rules.js +344 -0
- package/dist/packages/domain/src/constitution/observability/index.js +43 -0
- package/dist/packages/domain/src/constitution/observability/ts.rules.js +307 -0
- package/dist/packages/domain/src/constitution/performance/index.js +43 -0
- package/dist/packages/domain/src/constitution/performance/ts.rules.js +325 -0
- package/dist/packages/domain/src/constitution/security/index.js +50 -0
- package/dist/packages/domain/src/constitution/security/ts.rules.js +267 -0
- package/dist/packages/domain/src/constitution/soc/index.js +43 -0
- package/dist/packages/domain/src/constitution/soc/ts.rules.js +360 -0
- package/dist/packages/domain/src/contracts/analysis.contract.js +18 -0
- package/dist/packages/domain/src/contracts/index.js +7 -0
- package/dist/packages/domain/src/contracts/projects.contract.js +18 -0
- package/dist/packages/domain/src/control/registry/rules.registry.js +29 -0
- package/dist/packages/domain/src/control/schemas/policies.js +6 -0
- package/dist/packages/domain/src/core/analysis/discovery.js +163 -0
- package/dist/packages/domain/src/core/analysis/engine.contract.js +298 -0
- package/dist/packages/domain/src/core/analysis/engine.js +77 -0
- package/dist/packages/domain/src/core/analysis/index.js +14 -0
- package/dist/packages/domain/src/core/analysis/orchestrator.js +242 -0
- package/dist/packages/domain/src/core/comparison/engine.js +29 -0
- package/dist/packages/domain/src/core/comparison/index.js +5 -0
- package/dist/packages/domain/src/core/documentation/index.js +5 -0
- package/dist/packages/domain/src/core/documentation/pipeline.js +41 -0
- package/dist/packages/domain/src/core/fs/adapter.js +111 -0
- package/dist/packages/domain/src/core/fs/index.js +5 -0
- package/dist/packages/domain/src/core/parser/unified-parser.js +166 -0
- package/dist/packages/domain/src/index.js +33 -0
- package/dist/packages/domain/src/plugin/registry.js +195 -0
- package/dist/packages/domain/src/plugin/types.js +6 -0
- package/dist/packages/domain/src/ports/analysis.engine.js +7 -0
- package/dist/packages/domain/src/ports/audit.logger.js +7 -0
- package/dist/packages/domain/src/ports/project.repository.js +7 -0
- package/dist/packages/domain/src/rules/index.js +134 -0
- package/dist/packages/domain/src/types/analysis.js +6 -0
- package/dist/packages/domain/src/types/errors.js +53 -0
- package/dist/packages/domain/src/types/fs.js +6 -0
- package/dist/packages/domain/src/types/index.js +7 -0
- package/dist/plugins/GitStatusPlugin.js +93 -0
- package/dist/providers/ai-provider.js +74 -0
- package/dist/providers/local-provider.js +304 -0
- package/dist/providers/remote-provider.js +100 -0
- package/dist/types/api.js +3 -0
- package/dist/ui.js +219 -0
- package/dist/welcome.js +81 -0
- package/package.json +18 -18
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Command
|
|
3
|
+
* @description Main analysis command implementation
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { ProjectScanner } from '../scanners/project.scanner';
|
|
8
|
+
import { SecurityValidator } from '../validators/security.validator';
|
|
9
|
+
import { PerformanceValidator } from '../validators/performance.validator';
|
|
10
|
+
import { SocValidator } from '../validators/soc.validator';
|
|
11
|
+
import { ContractsValidator } from '../validators/contracts.validator';
|
|
12
|
+
import { MaintainabilityValidator } from '../validators/maintainability.validator';
|
|
13
|
+
import { ObservabilityValidator } from '../validators/observability.validator';
|
|
14
|
+
import { ReportGenerator } from '../generators/report.generator';
|
|
15
|
+
export async function analyzeCommand(projectPath, options) {
|
|
16
|
+
console.log(`🔍 Analyzing project: ${projectPath}`);
|
|
17
|
+
console.log(` Language: ${options.language}`);
|
|
18
|
+
console.log(` Depth: ${options.depth}`);
|
|
19
|
+
console.log('');
|
|
20
|
+
try {
|
|
21
|
+
// 1. Validate project path
|
|
22
|
+
const absolutePath = path.resolve(projectPath);
|
|
23
|
+
await fs.access(absolutePath);
|
|
24
|
+
// 2. Scan project structure
|
|
25
|
+
console.log('📁 Scanning project structure...');
|
|
26
|
+
const projectInfo = await ProjectScanner.scan(absolutePath, options.language);
|
|
27
|
+
// 3. Run validators
|
|
28
|
+
console.log('🔒 Validating Security...');
|
|
29
|
+
const securityResult = await SecurityValidator.validate(projectInfo, options);
|
|
30
|
+
console.log('⚡ Validating Performance...');
|
|
31
|
+
const performanceResult = await PerformanceValidator.validate(projectInfo, options);
|
|
32
|
+
console.log('🏗️ Validating Separation of Concerns...');
|
|
33
|
+
const socResult = await SocValidator.validate(projectInfo, options);
|
|
34
|
+
console.log('📋 Validating Contracts...');
|
|
35
|
+
const contractsResult = await ContractsValidator.validate(projectInfo, options);
|
|
36
|
+
console.log('🔧 Validating Maintainability...');
|
|
37
|
+
const maintainabilityResult = await MaintainabilityValidator.validate(projectInfo, options);
|
|
38
|
+
console.log('👁️ Validating Observability...');
|
|
39
|
+
const observabilityResult = await ObservabilityValidator.validate(projectInfo, options);
|
|
40
|
+
// 4. Calculate overall score
|
|
41
|
+
const scores = {
|
|
42
|
+
security: {
|
|
43
|
+
...securityResult,
|
|
44
|
+
weight: 25,
|
|
45
|
+
weightedScore: (securityResult.score / securityResult.maxScore) * 25,
|
|
46
|
+
},
|
|
47
|
+
performance: {
|
|
48
|
+
...performanceResult,
|
|
49
|
+
weight: 20,
|
|
50
|
+
weightedScore: (performanceResult.score / performanceResult.maxScore) * 20,
|
|
51
|
+
},
|
|
52
|
+
soc: { ...socResult, weight: 20, weightedScore: (socResult.score / socResult.maxScore) * 20 },
|
|
53
|
+
contracts: {
|
|
54
|
+
...contractsResult,
|
|
55
|
+
weight: 15,
|
|
56
|
+
weightedScore: (contractsResult.score / contractsResult.maxScore) * 15,
|
|
57
|
+
},
|
|
58
|
+
maintainability: {
|
|
59
|
+
...maintainabilityResult,
|
|
60
|
+
weight: 10,
|
|
61
|
+
weightedScore: (maintainabilityResult.score / maintainabilityResult.maxScore) * 10,
|
|
62
|
+
},
|
|
63
|
+
observability: {
|
|
64
|
+
...observabilityResult,
|
|
65
|
+
weight: 10,
|
|
66
|
+
weightedScore: (observabilityResult.score / observabilityResult.maxScore) * 10,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
const overallScore = Object.values(scores).reduce((sum, s) => sum + s.weightedScore, 0);
|
|
70
|
+
const percentage = Math.round(overallScore);
|
|
71
|
+
const grade = percentage >= 90
|
|
72
|
+
? 'A'
|
|
73
|
+
: percentage >= 80
|
|
74
|
+
? 'B'
|
|
75
|
+
: percentage >= 70
|
|
76
|
+
? 'C'
|
|
77
|
+
: percentage >= 60
|
|
78
|
+
? 'D'
|
|
79
|
+
: 'F';
|
|
80
|
+
// 5. Collect violations
|
|
81
|
+
const violations = [
|
|
82
|
+
...securityResult.violations.map(v => ({ ...v, axis: 'Security' })),
|
|
83
|
+
...performanceResult.violations.map(v => ({ ...v, axis: 'Performance' })),
|
|
84
|
+
...socResult.violations.map(v => ({ ...v, axis: 'SoC' })),
|
|
85
|
+
...contractsResult.violations.map(v => ({ ...v, axis: 'Contracts' })),
|
|
86
|
+
...maintainabilityResult.violations.map(v => ({ ...v, axis: 'Maintainability' })),
|
|
87
|
+
...observabilityResult.violations.map(v => ({ ...v, axis: 'Observability' })),
|
|
88
|
+
];
|
|
89
|
+
// 6. Generate recommendations
|
|
90
|
+
const recommendations = generateRecommendations(violations, scores);
|
|
91
|
+
// 7. Build result
|
|
92
|
+
const result = {
|
|
93
|
+
project: {
|
|
94
|
+
path: absolutePath,
|
|
95
|
+
name: path.basename(absolutePath),
|
|
96
|
+
language: options.language,
|
|
97
|
+
size: projectInfo.size,
|
|
98
|
+
fileCount: projectInfo.fileCount,
|
|
99
|
+
},
|
|
100
|
+
timestamp: new Date().toISOString(),
|
|
101
|
+
constitution: {
|
|
102
|
+
version: '0.5.0',
|
|
103
|
+
axes: ['security', 'performance', 'maintainability'],
|
|
104
|
+
},
|
|
105
|
+
scores,
|
|
106
|
+
overall: {
|
|
107
|
+
score: overallScore,
|
|
108
|
+
percentage,
|
|
109
|
+
grade,
|
|
110
|
+
compliant: violations.filter(v => v.severity === 'critical' || v.severity === 'error').length === 0,
|
|
111
|
+
},
|
|
112
|
+
violations,
|
|
113
|
+
recommendations,
|
|
114
|
+
};
|
|
115
|
+
// 8. Output results
|
|
116
|
+
await outputResults(result, options);
|
|
117
|
+
// 9. Exit with appropriate code
|
|
118
|
+
if (options.strict &&
|
|
119
|
+
violations.some(v => v.severity === 'critical' || v.severity === 'error')) {
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
console.error('❌ Analysis failed:', error instanceof Error ? error.message : String(error));
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function outputResults(result, options) {
|
|
129
|
+
switch (options.output) {
|
|
130
|
+
case 'json':
|
|
131
|
+
console.log(JSON.stringify(result, null, 2));
|
|
132
|
+
break;
|
|
133
|
+
case 'html':
|
|
134
|
+
{
|
|
135
|
+
const html = ReportGenerator.generateHTML(result);
|
|
136
|
+
const htmlPath = `${result.project.name}-analysis.html`;
|
|
137
|
+
await fs.writeFile(htmlPath, html);
|
|
138
|
+
console.log(`📄 HTML report saved to: ${htmlPath}`);
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
case 'markdown':
|
|
142
|
+
{
|
|
143
|
+
const markdown = ReportGenerator.generateMarkdown(result);
|
|
144
|
+
const mdPath = `${result.project.name}-analysis.md`;
|
|
145
|
+
await fs.writeFile(mdPath, markdown);
|
|
146
|
+
console.log(`📄 Markdown report saved to: ${mdPath}`);
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
default:
|
|
150
|
+
// Console output
|
|
151
|
+
printConsoleReport(result);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function printConsoleReport(result) {
|
|
155
|
+
console.log('\n' + '='.repeat(60));
|
|
156
|
+
console.log('📊 DELTA CONSTITUTION ANALYSIS REPORT');
|
|
157
|
+
console.log('='.repeat(60));
|
|
158
|
+
console.log(`\nProject: ${result.project.name}`);
|
|
159
|
+
console.log(`Path: ${result.project.path}`);
|
|
160
|
+
console.log(`Language: ${result.project.language}`);
|
|
161
|
+
console.log(`Files: ${result.project.fileCount}`);
|
|
162
|
+
console.log(`Constitution: v${result.constitution.version}`);
|
|
163
|
+
console.log(`\n${'-'.repeat(60)}`);
|
|
164
|
+
console.log(`\n🎯 OVERALL SCORE: ${result.overall.percentage}% (Grade: ${result.overall.grade})`);
|
|
165
|
+
console.log(`Status: ${result.overall.compliant ? '✅ Compliant' : '❌ Non-Compliant'}`);
|
|
166
|
+
console.log(`\n${'-'.repeat(60)}`);
|
|
167
|
+
console.log('AXIS SCORES:');
|
|
168
|
+
console.log(`${'-'.repeat(60)}`);
|
|
169
|
+
Object.entries(result.scores).forEach(([axis, score]) => {
|
|
170
|
+
const bar = '█'.repeat(Math.round(score.percentage / 5)) +
|
|
171
|
+
'░'.repeat(20 - Math.round(score.percentage / 5));
|
|
172
|
+
console.log(`${axis.padEnd(20)} ${bar} ${score.percentage.toString().padStart(3)}%`);
|
|
173
|
+
});
|
|
174
|
+
if (result.violations.length > 0) {
|
|
175
|
+
console.log(`\n${'-'.repeat(60)}`);
|
|
176
|
+
console.log('VIOLATIONS:');
|
|
177
|
+
console.log(`${'-'.repeat(60)}`);
|
|
178
|
+
const critical = result.violations.filter(v => v.severity === 'critical');
|
|
179
|
+
const errors = result.violations.filter(v => v.severity === 'error');
|
|
180
|
+
const warnings = result.violations.filter(v => v.severity === 'warning');
|
|
181
|
+
if (critical.length > 0) {
|
|
182
|
+
console.log('\n🔴 Critical:');
|
|
183
|
+
critical.forEach(v => console.log(` - [${v.id}] ${v.message}`));
|
|
184
|
+
}
|
|
185
|
+
if (errors.length > 0) {
|
|
186
|
+
console.log('\n🟠 Errors:');
|
|
187
|
+
errors.forEach(v => console.log(` - [${v.id}] ${v.message}`));
|
|
188
|
+
}
|
|
189
|
+
if (warnings.length > 0) {
|
|
190
|
+
console.log('\n🟡 Warnings:');
|
|
191
|
+
warnings.slice(0, 5).forEach(v => console.log(` - [${v.id}] ${v.message}`));
|
|
192
|
+
if (warnings.length > 5) {
|
|
193
|
+
console.log(` ... and ${warnings.length - 5} more warnings`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (result.recommendations.length > 0) {
|
|
198
|
+
console.log(`\n${'-'.repeat(60)}`);
|
|
199
|
+
console.log('TOP RECOMMENDATIONS:');
|
|
200
|
+
console.log(`${'-'.repeat(60)}`);
|
|
201
|
+
result.recommendations
|
|
202
|
+
.filter(r => r.priority === 'high')
|
|
203
|
+
.slice(0, 5)
|
|
204
|
+
.forEach(r => {
|
|
205
|
+
console.log(`\n[${r.axis}] ${r.description}`);
|
|
206
|
+
console.log(` Action: ${r.action}`);
|
|
207
|
+
console.log(` Effort: ${r.effort}`);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
console.log('\n' + '='.repeat(60) + '\n');
|
|
211
|
+
}
|
|
212
|
+
function generateRecommendations(violations, scores) {
|
|
213
|
+
const recommendations = [];
|
|
214
|
+
// Security recommendations
|
|
215
|
+
if (scores.security.percentage < 80) {
|
|
216
|
+
recommendations.push({
|
|
217
|
+
axis: 'Security',
|
|
218
|
+
priority: 'high',
|
|
219
|
+
description: 'Security score below 80%',
|
|
220
|
+
action: 'Implement Policy Guards, Audit Logging, and Fail-Closed patterns',
|
|
221
|
+
effort: '2-3 days',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// Performance recommendations
|
|
225
|
+
if (scores.performance.percentage < 70) {
|
|
226
|
+
recommendations.push({
|
|
227
|
+
axis: 'Performance',
|
|
228
|
+
priority: 'medium',
|
|
229
|
+
description: 'Performance optimizations needed',
|
|
230
|
+
action: 'Add lazy loading, code splitting, and caching layers',
|
|
231
|
+
effort: '1-2 days',
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
// SoC recommendations
|
|
235
|
+
if (scores.soc.percentage < 80) {
|
|
236
|
+
recommendations.push({
|
|
237
|
+
axis: 'SoC',
|
|
238
|
+
priority: 'high',
|
|
239
|
+
description: 'Layer boundaries need improvement',
|
|
240
|
+
action: 'Refactor to follow 7-layer architecture, fix import violations',
|
|
241
|
+
effort: '3-5 days',
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
// Add specific recommendations based on violations
|
|
245
|
+
const failClosedViolations = violations.filter(v => v.message.includes('Fail-Open'));
|
|
246
|
+
if (failClosedViolations.length > 0) {
|
|
247
|
+
recommendations.push({
|
|
248
|
+
axis: 'Security',
|
|
249
|
+
priority: 'high',
|
|
250
|
+
description: `Found ${failClosedViolations.length} Fail-Open patterns`,
|
|
251
|
+
action: 'Replace with Fail-Closed: if (!isAllowed) return deny()',
|
|
252
|
+
effort: '1 day',
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return recommendations.sort((a, b) => {
|
|
256
|
+
const priorityOrder = { high: 0, medium: 1, low: 2 };
|
|
257
|
+
return priorityOrder[a.priority] - priorityOrder[b.priority];
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Command
|
|
3
|
+
* @description Manage analyzer configuration
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
const DEFAULT_CONFIG = {
|
|
8
|
+
version: '1.0.0',
|
|
9
|
+
language: 'typescript',
|
|
10
|
+
depth: 'standard',
|
|
11
|
+
output: 'json',
|
|
12
|
+
strict: false,
|
|
13
|
+
rules: {
|
|
14
|
+
security: { enabled: true, weight: 25 },
|
|
15
|
+
performance: { enabled: true, weight: 20 },
|
|
16
|
+
soc: { enabled: true, weight: 20 },
|
|
17
|
+
contracts: { enabled: true, weight: 15 },
|
|
18
|
+
maintainability: { enabled: true, weight: 10 },
|
|
19
|
+
observability: { enabled: true, weight: 10 },
|
|
20
|
+
},
|
|
21
|
+
thresholds: {
|
|
22
|
+
critical: 0,
|
|
23
|
+
error: 5,
|
|
24
|
+
warning: 20,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export async function configCommand(options) {
|
|
28
|
+
const configPath = path.join(process.cwd(), '.delta-analyzer.json');
|
|
29
|
+
if (options.init) {
|
|
30
|
+
try {
|
|
31
|
+
await fs.writeFile(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
|
|
32
|
+
console.log('✅ Configuration file created: .delta-analyzer.json');
|
|
33
|
+
console.log('\nEdit this file to customize analyzer settings.');
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.error('❌ Failed to create config:', error instanceof Error ? error.message : String(error));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (options.show) {
|
|
42
|
+
try {
|
|
43
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
44
|
+
const config = JSON.parse(content);
|
|
45
|
+
console.log('\n📋 Current Configuration:\n');
|
|
46
|
+
console.log(JSON.stringify(config, null, 2));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
console.log('⚠️ No configuration file found. Run with --init to create one.');
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (options.set) {
|
|
54
|
+
const [key, value] = options.set.split('=');
|
|
55
|
+
if (!key || !value) {
|
|
56
|
+
console.error('❌ Invalid format. Use: --set key=value');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
61
|
+
const config = JSON.parse(content);
|
|
62
|
+
// Simple nested key support (e.g., "rules.security.enabled")
|
|
63
|
+
const keys = key.split('.');
|
|
64
|
+
let current = config;
|
|
65
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
66
|
+
current = current[keys[i]];
|
|
67
|
+
}
|
|
68
|
+
current[keys[keys.length - 1]] = value;
|
|
69
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
70
|
+
console.log(`✅ Set ${key} = ${value}`);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
console.log('⚠️ No configuration file found. Run with --init to create one.');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log('Usage:');
|
|
79
|
+
console.log(' delta-analyze config --init Create default configuration');
|
|
80
|
+
console.log(' delta-analyze config --show Show current configuration');
|
|
81
|
+
console.log(' delta-analyze config --set key=value Set configuration value');
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Command
|
|
3
|
+
* @description Generate report from previous analysis
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import { ReportGenerator } from '../generators/report.generator';
|
|
7
|
+
export async function reportCommand(analysisFile, options) {
|
|
8
|
+
try {
|
|
9
|
+
// Read analysis file
|
|
10
|
+
const content = await fs.readFile(analysisFile, 'utf-8');
|
|
11
|
+
const analysis = JSON.parse(content);
|
|
12
|
+
// Generate report
|
|
13
|
+
let output;
|
|
14
|
+
let extension;
|
|
15
|
+
switch (options.template) {
|
|
16
|
+
case 'html':
|
|
17
|
+
output = ReportGenerator.generateHTML(analysis);
|
|
18
|
+
extension = 'html';
|
|
19
|
+
break;
|
|
20
|
+
case 'markdown':
|
|
21
|
+
output = ReportGenerator.generateMarkdown(analysis);
|
|
22
|
+
extension = 'md';
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
console.error(`Unknown template: ${options.template}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
// Write to file
|
|
29
|
+
const outputPath = options.output || `${analysis.project.name}-report.${extension}`;
|
|
30
|
+
await fs.writeFile(outputPath, output);
|
|
31
|
+
console.log(`✅ Report generated: ${outputPath}`);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('❌ Failed to generate report:', error instanceof Error ? error.message : String(error));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report Generator
|
|
3
|
+
* @description Generates analysis reports in various formats
|
|
4
|
+
*/
|
|
5
|
+
export class ReportGenerator {
|
|
6
|
+
static generateHTML(result) {
|
|
7
|
+
return `<!DOCTYPE html>
|
|
8
|
+
<html>
|
|
9
|
+
<head>
|
|
10
|
+
<title>Delta Analysis - ${result.project.name}</title>
|
|
11
|
+
<style>
|
|
12
|
+
body { font-family: system-ui, sans-serif; max-width: 900px; margin: 0 auto; padding: 20px; }
|
|
13
|
+
.header { background: #1a1a2e; color: white; padding: 30px; border-radius: 8px; margin-bottom: 20px; }
|
|
14
|
+
.score { font-size: 48px; font-weight: bold; }
|
|
15
|
+
.grade { font-size: 24px; opacity: 0.8; }
|
|
16
|
+
.axis { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 6px; }
|
|
17
|
+
.bar { background: #ddd; height: 20px; border-radius: 10px; overflow: hidden; }
|
|
18
|
+
.bar-fill { background: #4CAF50; height: 100%; transition: width 0.3s; }
|
|
19
|
+
.violation { padding: 10px; margin: 5px 0; border-left: 4px solid; }
|
|
20
|
+
.critical { border-color: #f44336; background: #ffebee; }
|
|
21
|
+
.error { border-color: #ff9800; background: #fff3e0; }
|
|
22
|
+
.warning { border-color: #ffeb3b; background: #fffde7; }
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div class="header">
|
|
27
|
+
<h1>📊 Delta Constitution Analysis</h1>
|
|
28
|
+
<div class="score">${result.overall.percentage}%</div>
|
|
29
|
+
<div class="grade">Grade: ${result.overall.grade}</div>
|
|
30
|
+
<p>Project: ${result.project.name} | ${result.project.fileCount} files</p>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<h2>Axis Scores</h2>
|
|
34
|
+
${Object.entries(result.scores)
|
|
35
|
+
.map(([name, score]) => `
|
|
36
|
+
<div class="axis">
|
|
37
|
+
<strong>${name}</strong>: ${score.percentage}%
|
|
38
|
+
<div class="bar"><div class="bar-fill" style="width: ${score.percentage}%"></div></div>
|
|
39
|
+
</div>
|
|
40
|
+
`)
|
|
41
|
+
.join('')}
|
|
42
|
+
|
|
43
|
+
<h2>Violations (${result.violations.length})</h2>
|
|
44
|
+
${result.violations
|
|
45
|
+
.slice(0, 20)
|
|
46
|
+
.map(v => `
|
|
47
|
+
<div class="violation ${v.severity}">
|
|
48
|
+
<strong>[${v.axis}] ${v.id}</strong>: ${v.message}
|
|
49
|
+
</div>
|
|
50
|
+
`)
|
|
51
|
+
.join('')}
|
|
52
|
+
|
|
53
|
+
<h2>Recommendations</h2>
|
|
54
|
+
${result.recommendations
|
|
55
|
+
.slice(0, 5)
|
|
56
|
+
.map(r => `
|
|
57
|
+
<div class="axis">
|
|
58
|
+
<strong>[${r.axis}] ${r.priority}</strong>
|
|
59
|
+
<p>${r.description}</p>
|
|
60
|
+
<small>Action: ${r.action}</small>
|
|
61
|
+
</div>
|
|
62
|
+
`)
|
|
63
|
+
.join('')}
|
|
64
|
+
|
|
65
|
+
<footer style="margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #666;">
|
|
66
|
+
Generated: ${result.timestamp} | Delta Constitution v1.0.0
|
|
67
|
+
</footer>
|
|
68
|
+
</body>
|
|
69
|
+
</html>`;
|
|
70
|
+
}
|
|
71
|
+
static generateMarkdown(result) {
|
|
72
|
+
return `# Delta Constitution Analysis Report
|
|
73
|
+
|
|
74
|
+
## Project: ${result.project.name}
|
|
75
|
+
|
|
76
|
+
- **Path**: ${result.project.path}
|
|
77
|
+
- **Language**: ${result.project.language}
|
|
78
|
+
- **Files**: ${result.project.fileCount}
|
|
79
|
+
- **Generated**: ${result.timestamp}
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Overall Score: ${result.overall.percentage}% (Grade: ${result.overall.grade})
|
|
84
|
+
|
|
85
|
+
**Status**: ${result.overall.compliant ? '✅ Compliant' : '❌ Non-Compliant'}
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Axis Scores
|
|
90
|
+
|
|
91
|
+
| Axis | Score | Weight | Status |
|
|
92
|
+
|------|-------|--------|--------|
|
|
93
|
+
${Object.entries(result.scores)
|
|
94
|
+
.map(([name, s]) => `| ${name} | ${s.percentage}% | ${s.weight}% | ${s.percentage >= 70 ? '✅' : '⚠️'} |`)
|
|
95
|
+
.join('\n')}
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Violations (${result.violations.length})
|
|
100
|
+
|
|
101
|
+
${result.violations
|
|
102
|
+
.slice(0, 30)
|
|
103
|
+
.map(v => `- **[${v.axis}]** \`${v.id}\` (${v.severity}): ${v.message}`)
|
|
104
|
+
.join('\n')}
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Top Recommendations
|
|
109
|
+
|
|
110
|
+
${result.recommendations
|
|
111
|
+
.slice(0, 10)
|
|
112
|
+
.map((r, i) => `${i + 1}. **[${r.axis}]** ${r.description}
|
|
113
|
+
- Priority: ${r.priority}
|
|
114
|
+
- Action: ${r.action}`)
|
|
115
|
+
.join('\n\n')}
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
*Report generated by Delta Analyzer v1.0.0*
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=report.generator.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Delta CLI Analyzer
|
|
4
|
+
* @description Analyze projects against Delta Constitution
|
|
5
|
+
* @version 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { analyzeCommand } from './commands/analyze';
|
|
9
|
+
import { reportCommand } from './commands/report';
|
|
10
|
+
import { configCommand } from './commands/config';
|
|
11
|
+
const program = new Command();
|
|
12
|
+
program
|
|
13
|
+
.name('delta-analyze')
|
|
14
|
+
.description('Analyze projects against Delta Constitution')
|
|
15
|
+
.version('1.0.0');
|
|
16
|
+
// Analyze command
|
|
17
|
+
program
|
|
18
|
+
.command('analyze')
|
|
19
|
+
.description('Analyze a project against Delta Constitution')
|
|
20
|
+
.argument('<path>', 'Project path to analyze')
|
|
21
|
+
.option('-l, --language <lang>', 'Project language', 'typescript')
|
|
22
|
+
.option('-o, --output <format>', 'Output format (json|html|markdown)', 'json')
|
|
23
|
+
.option('-d, --depth <level>', 'Analysis depth (quick|standard|deep)', 'standard')
|
|
24
|
+
.option('--config <path>', 'Configuration file path')
|
|
25
|
+
.option('--strict', 'Fail on any violation', false)
|
|
26
|
+
.action(analyzeCommand);
|
|
27
|
+
// Report command
|
|
28
|
+
program
|
|
29
|
+
.command('report')
|
|
30
|
+
.description('Generate report from previous analysis')
|
|
31
|
+
.argument('<analysis-file>', 'Previous analysis JSON file')
|
|
32
|
+
.option('-t, --template <type>', 'Report template (html|markdown|pdf)', 'html')
|
|
33
|
+
.option('-o, --output <path>', 'Output file path')
|
|
34
|
+
.action(reportCommand);
|
|
35
|
+
// Config command
|
|
36
|
+
program
|
|
37
|
+
.command('config')
|
|
38
|
+
.description('Manage analyzer configuration')
|
|
39
|
+
.option('--init', 'Initialize configuration file')
|
|
40
|
+
.option('--show', 'Show current configuration')
|
|
41
|
+
.option('--set <key=value>', 'Set configuration value')
|
|
42
|
+
.action(configCommand);
|
|
43
|
+
program.parse();
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Scanner
|
|
3
|
+
* @description Scans project structure and extracts metadata
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
export class ProjectScanner {
|
|
8
|
+
static async scan(projectPath, language) {
|
|
9
|
+
const files = [];
|
|
10
|
+
const directories = [];
|
|
11
|
+
const totalSize = 0;
|
|
12
|
+
// Scan directory recursively
|
|
13
|
+
await this.scanDirectory(projectPath, '', files, directories, totalSize);
|
|
14
|
+
// Detect project metadata
|
|
15
|
+
const hasPackageJson = files.some(f => f.endsWith('package.json'));
|
|
16
|
+
const hasTsConfig = files.some(f => f.endsWith('tsconfig.json'));
|
|
17
|
+
const hasTests = files.some(f => f.includes('.test.') || f.includes('.spec.'));
|
|
18
|
+
// Extract imports
|
|
19
|
+
const imports = await this.extractImports(files, projectPath);
|
|
20
|
+
return {
|
|
21
|
+
path: projectPath,
|
|
22
|
+
name: path.basename(projectPath),
|
|
23
|
+
language,
|
|
24
|
+
size: totalSize,
|
|
25
|
+
fileCount: files.length,
|
|
26
|
+
files,
|
|
27
|
+
directories,
|
|
28
|
+
imports,
|
|
29
|
+
hasPackageJson,
|
|
30
|
+
hasTsConfig,
|
|
31
|
+
hasTests,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
static async scanDirectory(basePath, relativePath, files, directories, totalSize) {
|
|
35
|
+
const fullPath = path.join(basePath, relativePath);
|
|
36
|
+
try {
|
|
37
|
+
const entries = await fs.readdir(fullPath, { withFileTypes: true });
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const entryRelativePath = path.join(relativePath, entry.name);
|
|
40
|
+
// Skip node_modules and hidden directories
|
|
41
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.')) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
directories.push(entryRelativePath);
|
|
46
|
+
await this.scanDirectory(basePath, entryRelativePath, files, directories, totalSize);
|
|
47
|
+
}
|
|
48
|
+
else if (entry.isFile()) {
|
|
49
|
+
// Only include source files
|
|
50
|
+
if (this.isSourceFile(entry.name)) {
|
|
51
|
+
files.push(entryRelativePath);
|
|
52
|
+
const stats = await fs.stat(path.join(fullPath, entry.name));
|
|
53
|
+
totalSize += stats.size;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// Directory not accessible, skip
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
static isSourceFile(filename) {
|
|
63
|
+
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.json', '.md'];
|
|
64
|
+
return extensions.some(ext => filename.endsWith(ext));
|
|
65
|
+
}
|
|
66
|
+
static async extractImports(files, projectPath) {
|
|
67
|
+
const imports = [];
|
|
68
|
+
for (const file of files) {
|
|
69
|
+
if (!file.endsWith('.ts') && !file.endsWith('.tsx'))
|
|
70
|
+
continue;
|
|
71
|
+
try {
|
|
72
|
+
const content = await fs.readFile(path.join(projectPath, file), 'utf-8');
|
|
73
|
+
const importMatches = content.match(/import\s+.*?\s+from\s+['"]([^'"]+)['"];?/g) || [];
|
|
74
|
+
for (const match of importMatches) {
|
|
75
|
+
const importPath = match.match(/from\s+['"]([^'"]+)['"]/)?.[1];
|
|
76
|
+
if (importPath) {
|
|
77
|
+
imports.push({
|
|
78
|
+
source: file,
|
|
79
|
+
target: importPath,
|
|
80
|
+
type: importPath.startsWith('.') ? 'internal' : 'external',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
// Skip files that can't be read
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return imports;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=project.scanner.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contracts Validator
|
|
3
|
+
* @description Validates Contracts rules
|
|
4
|
+
*/
|
|
5
|
+
export class ContractsValidator {
|
|
6
|
+
static async validate(project, _options) {
|
|
7
|
+
const violations = [];
|
|
8
|
+
let score = 100;
|
|
9
|
+
// Check for contract files
|
|
10
|
+
const contractFiles = project.files.filter(f => f.includes('.contract.'));
|
|
11
|
+
if (contractFiles.length === 0) {
|
|
12
|
+
violations.push({
|
|
13
|
+
id: 'CONTRACT-001',
|
|
14
|
+
severity: 'error',
|
|
15
|
+
message: 'No contract files found',
|
|
16
|
+
rule: 'Contracts Required',
|
|
17
|
+
});
|
|
18
|
+
score -= 30;
|
|
19
|
+
}
|
|
20
|
+
// Check for required contracts
|
|
21
|
+
const requiredContracts = ['auth', 'upload', 'projects', 'analysis'];
|
|
22
|
+
for (const contract of requiredContracts) {
|
|
23
|
+
const hasContract = contractFiles.some(f => f.includes(`${contract}.contract`));
|
|
24
|
+
if (!hasContract) {
|
|
25
|
+
violations.push({
|
|
26
|
+
id: 'CONTRACT-002',
|
|
27
|
+
severity: 'warning',
|
|
28
|
+
message: `Missing ${contract}.contract.ts`,
|
|
29
|
+
rule: 'Required Contracts',
|
|
30
|
+
});
|
|
31
|
+
score -= 10;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
score: Math.max(0, score),
|
|
36
|
+
maxScore: 100,
|
|
37
|
+
percentage: Math.max(0, score),
|
|
38
|
+
violations,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=contracts.validator.js.map
|