@vee-stack/delta-cli 2.0.3 → 2.0.5
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 -46
- package/dist/commands/analyze.js +363 -0
- package/dist/commands/auth-new.js +37 -0
- package/dist/commands/auth.js +133 -0
- package/dist/commands/config.js +50 -0
- package/dist/commands/deploy.js +6 -0
- package/dist/commands/init.js +47 -0
- package/dist/commands/logout.js +30 -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 +71 -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,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Analysis Engine - Contract v1 Implementation
|
|
3
|
+
* @description Stateless pipeline implementing AnalysisEngine contract
|
|
4
|
+
* @implements AnalysisEngine from @/contracts/analysis.contract.js
|
|
5
|
+
* @module core/analysis
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
import { ANALYSIS_CONTRACT_VERSION, } from '../../contracts/analysis.contract.js';
|
|
9
|
+
import { rulesRegistry } from '../../control/registry/rules.registry.js';
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// ENGINE IMPLEMENTATION
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Analysis Engine v1.0.0
|
|
15
|
+
* Implements AnalysisEngine contract
|
|
16
|
+
*/
|
|
17
|
+
export class AnalysisEngineV1 {
|
|
18
|
+
/** Engine version */
|
|
19
|
+
version = '1.0.0';
|
|
20
|
+
/** Supported languages */
|
|
21
|
+
supportedLanguages = [
|
|
22
|
+
'typescript',
|
|
23
|
+
'javascript',
|
|
24
|
+
'python',
|
|
25
|
+
'java',
|
|
26
|
+
'go',
|
|
27
|
+
'rust',
|
|
28
|
+
'c',
|
|
29
|
+
'cpp',
|
|
30
|
+
'csharp',
|
|
31
|
+
'php',
|
|
32
|
+
'ruby',
|
|
33
|
+
'swift',
|
|
34
|
+
'kotlin',
|
|
35
|
+
'sql',
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Analyze a complete project
|
|
39
|
+
*/
|
|
40
|
+
async analyzeProject(input) {
|
|
41
|
+
const startTime = Date.now();
|
|
42
|
+
const fileResults = [];
|
|
43
|
+
for (const file of input.files) {
|
|
44
|
+
const result = await this.analyzeFile(file, input.config);
|
|
45
|
+
fileResults.push(result);
|
|
46
|
+
}
|
|
47
|
+
const duration = Date.now() - startTime;
|
|
48
|
+
const summary = this.summarizeFindings(fileResults);
|
|
49
|
+
return {
|
|
50
|
+
id: this.generateId(),
|
|
51
|
+
timestamp: new Date(),
|
|
52
|
+
projectId: input.projectId,
|
|
53
|
+
duration,
|
|
54
|
+
files: fileResults,
|
|
55
|
+
summary,
|
|
56
|
+
engineVersion: this.version,
|
|
57
|
+
contractVersion: ANALYSIS_CONTRACT_VERSION,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Analyze a single file
|
|
62
|
+
*/
|
|
63
|
+
async analyzeFile(file, config) {
|
|
64
|
+
const startTime = Date.now();
|
|
65
|
+
// Validate language support
|
|
66
|
+
if (!this.supportsLanguage(file.language)) {
|
|
67
|
+
return {
|
|
68
|
+
filePath: file.path,
|
|
69
|
+
language: file.language,
|
|
70
|
+
lines: this.countLines(file.content),
|
|
71
|
+
findings: [],
|
|
72
|
+
duration: Date.now() - startTime,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Convert to internal format
|
|
76
|
+
const policies = await this.loadPolicies(config);
|
|
77
|
+
const findings = this.runAnalysis(file, policies);
|
|
78
|
+
return {
|
|
79
|
+
filePath: file.path,
|
|
80
|
+
language: file.language,
|
|
81
|
+
lines: this.countLines(file.content),
|
|
82
|
+
findings,
|
|
83
|
+
duration: Date.now() - startTime,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if language is supported
|
|
88
|
+
*/
|
|
89
|
+
supportsLanguage(language) {
|
|
90
|
+
return this.supportedLanguages.includes(language.toLowerCase());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get supported languages
|
|
94
|
+
*/
|
|
95
|
+
getSupportedLanguages() {
|
|
96
|
+
return [...this.supportedLanguages];
|
|
97
|
+
}
|
|
98
|
+
// =============================================================================
|
|
99
|
+
// INTERNAL METHODS (Private - not part of contract)
|
|
100
|
+
// =============================================================================
|
|
101
|
+
/**
|
|
102
|
+
* Load policies from config
|
|
103
|
+
*/
|
|
104
|
+
async loadPolicies(config) {
|
|
105
|
+
void config;
|
|
106
|
+
// TODO: Load from policy registry based on config.policies
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Run analysis with policies
|
|
111
|
+
*/
|
|
112
|
+
runAnalysis(file, policies) {
|
|
113
|
+
const findings = [];
|
|
114
|
+
void file.content.split('\n');
|
|
115
|
+
const ruleInput = {
|
|
116
|
+
file: file.path,
|
|
117
|
+
content: file.content,
|
|
118
|
+
language: file.language,
|
|
119
|
+
project: {
|
|
120
|
+
root: file.path,
|
|
121
|
+
config: {},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
// Apply enabled policies
|
|
125
|
+
for (const policy of policies) {
|
|
126
|
+
if (!policy.enabled)
|
|
127
|
+
continue;
|
|
128
|
+
try {
|
|
129
|
+
const ruleFindings = rulesRegistry.execute(policy.id, ruleInput, policy);
|
|
130
|
+
// Convert internal findings to contract format
|
|
131
|
+
for (const finding of ruleFindings) {
|
|
132
|
+
findings.push({
|
|
133
|
+
id: this.generateFindingId(),
|
|
134
|
+
severity: this.mapSeverity(finding.severity || 'info'),
|
|
135
|
+
category: this.mapCategory(policy.category || 'maintainability'),
|
|
136
|
+
message: finding.message,
|
|
137
|
+
filePath: file.path,
|
|
138
|
+
line: finding.location?.line ?? 1,
|
|
139
|
+
column: finding.location?.column ?? 0,
|
|
140
|
+
endLine: finding.location?.endLine,
|
|
141
|
+
endColumn: finding.location?.endColumn,
|
|
142
|
+
ruleId: policy.id,
|
|
143
|
+
ruleUrl: finding.documentation,
|
|
144
|
+
suggestedFix: finding.suggestion
|
|
145
|
+
? {
|
|
146
|
+
description: finding.suggestion,
|
|
147
|
+
}
|
|
148
|
+
: undefined,
|
|
149
|
+
metadata: finding.metadata,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
// Log but don't fail - one broken rule shouldn't stop analysis
|
|
155
|
+
console.error(`Policy ${policy.id} failed:`, error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return findings;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Summarize findings across all files
|
|
162
|
+
*/
|
|
163
|
+
summarizeFindings(files) {
|
|
164
|
+
const bySeverity = {
|
|
165
|
+
critical: 0,
|
|
166
|
+
high: 0,
|
|
167
|
+
medium: 0,
|
|
168
|
+
low: 0,
|
|
169
|
+
info: 0,
|
|
170
|
+
};
|
|
171
|
+
const byCategory = {
|
|
172
|
+
security: 0,
|
|
173
|
+
performance: 0,
|
|
174
|
+
architecture: 0,
|
|
175
|
+
maintainability: 0,
|
|
176
|
+
documentation: 0,
|
|
177
|
+
testing: 0,
|
|
178
|
+
style: 0,
|
|
179
|
+
};
|
|
180
|
+
let total = 0;
|
|
181
|
+
for (const file of files) {
|
|
182
|
+
for (const finding of file.findings) {
|
|
183
|
+
bySeverity[finding.severity]++;
|
|
184
|
+
byCategory[finding.category]++;
|
|
185
|
+
total++;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return { bySeverity, byCategory, total };
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Count lines in content
|
|
192
|
+
*/
|
|
193
|
+
countLines(content) {
|
|
194
|
+
return content.split('\n').length;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Map internal severity to contract severity
|
|
198
|
+
*/
|
|
199
|
+
mapSeverity(severity) {
|
|
200
|
+
const mapping = {
|
|
201
|
+
critical: 'critical',
|
|
202
|
+
error: 'high',
|
|
203
|
+
warning: 'medium',
|
|
204
|
+
info: 'info',
|
|
205
|
+
};
|
|
206
|
+
return mapping[severity] || 'info';
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Map internal category to contract category
|
|
210
|
+
*/
|
|
211
|
+
mapCategory(category) {
|
|
212
|
+
const mapping = {
|
|
213
|
+
security: 'security',
|
|
214
|
+
performance: 'performance',
|
|
215
|
+
architecture: 'architecture',
|
|
216
|
+
maintainability: 'maintainability',
|
|
217
|
+
documentation: 'documentation',
|
|
218
|
+
testing: 'testing',
|
|
219
|
+
style: 'style',
|
|
220
|
+
};
|
|
221
|
+
return mapping[category] || 'maintainability';
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Generate unique analysis ID
|
|
225
|
+
*/
|
|
226
|
+
generateId() {
|
|
227
|
+
return `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Generate finding ID
|
|
231
|
+
*/
|
|
232
|
+
generateFindingId() {
|
|
233
|
+
return `finding_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// =============================================================================
|
|
237
|
+
// LEGACY COMPATIBILITY
|
|
238
|
+
// =============================================================================
|
|
239
|
+
/**
|
|
240
|
+
* Legacy analyze function (maintained for backward compatibility)
|
|
241
|
+
* @deprecated Use AnalysisEngineV1.analyzeProject instead
|
|
242
|
+
*/
|
|
243
|
+
export function analyze(files, config, policies) {
|
|
244
|
+
void config;
|
|
245
|
+
void new AnalysisEngineV1();
|
|
246
|
+
const startTime = Date.now();
|
|
247
|
+
const findings = [];
|
|
248
|
+
for (const file of files) {
|
|
249
|
+
// Simplified analysis - full implementation uses engine.analyzeFile
|
|
250
|
+
const fileFindings = runLegacyAnalysis(file.path, file.content, file.language, policies);
|
|
251
|
+
findings.push(...fileFindings);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
findings,
|
|
255
|
+
duration: Date.now() - startTime,
|
|
256
|
+
filesAnalyzed: files.length,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Legacy analysis helper
|
|
261
|
+
*/
|
|
262
|
+
function runLegacyAnalysis(path, content, language, policies) {
|
|
263
|
+
const findings = [];
|
|
264
|
+
const ruleInput = {
|
|
265
|
+
file: path,
|
|
266
|
+
content,
|
|
267
|
+
language,
|
|
268
|
+
project: { root: path, config: {} },
|
|
269
|
+
};
|
|
270
|
+
for (const policy of policies) {
|
|
271
|
+
if (!policy.enabled)
|
|
272
|
+
continue;
|
|
273
|
+
try {
|
|
274
|
+
const ruleFindings = rulesRegistry.execute(policy.id, ruleInput, policy);
|
|
275
|
+
for (const f of ruleFindings) {
|
|
276
|
+
findings.push({
|
|
277
|
+
id: `legacy_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
|
|
278
|
+
severity: f.severity || 'info',
|
|
279
|
+
category: 'maintainability',
|
|
280
|
+
message: f.message,
|
|
281
|
+
filePath: path,
|
|
282
|
+
line: f.location?.line ?? 1,
|
|
283
|
+
column: f.location?.column ?? 0,
|
|
284
|
+
ruleId: policy.id,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
// Ignore errors in legacy mode
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return findings;
|
|
293
|
+
}
|
|
294
|
+
// =============================================================================
|
|
295
|
+
// EXPORTS
|
|
296
|
+
// =============================================================================
|
|
297
|
+
export { ANALYSIS_CONTRACT_VERSION };
|
|
298
|
+
//# sourceMappingURL=engine.contract.js.map
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core Analysis Engine
|
|
3
|
+
* Stateless pipeline for code analysis
|
|
4
|
+
* @see docs/architecture/OVERVIEW.md#data-flow
|
|
5
|
+
* @module core/analysis
|
|
6
|
+
*/
|
|
7
|
+
import { rulesRegistry } from '../../control/registry/rules.registry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Analysis Session
|
|
10
|
+
* Manages a single analysis run with frozen configuration
|
|
11
|
+
*/
|
|
12
|
+
export class AnalysisSession {
|
|
13
|
+
context;
|
|
14
|
+
constructor(config, policies) {
|
|
15
|
+
this.context = {
|
|
16
|
+
config: Object.freeze({ ...config }),
|
|
17
|
+
policies: [...policies],
|
|
18
|
+
startTime: Date.now(),
|
|
19
|
+
version: '1.0.0',
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get immutable context
|
|
24
|
+
*/
|
|
25
|
+
getContext() {
|
|
26
|
+
return this.context;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Analyze a single file
|
|
30
|
+
*/
|
|
31
|
+
analyzeFile(file, content, language) {
|
|
32
|
+
const ruleInput = {
|
|
33
|
+
file,
|
|
34
|
+
content,
|
|
35
|
+
language,
|
|
36
|
+
project: {
|
|
37
|
+
root: this.context.config.version,
|
|
38
|
+
config: {},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
const findings = [];
|
|
42
|
+
// Apply all enabled policies
|
|
43
|
+
for (const policy of this.context.policies) {
|
|
44
|
+
if (!policy.enabled)
|
|
45
|
+
continue;
|
|
46
|
+
const ruleResult = rulesRegistry.execute(policy.id, ruleInput, policy);
|
|
47
|
+
findings.push(...ruleResult);
|
|
48
|
+
}
|
|
49
|
+
return findings;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Analysis Pipeline
|
|
54
|
+
* Pure function: input -> rules -> output
|
|
55
|
+
*/
|
|
56
|
+
export function analyze(files, config, policies) {
|
|
57
|
+
const startTime = Date.now();
|
|
58
|
+
const session = new AnalysisSession(config, policies);
|
|
59
|
+
const allFindings = [];
|
|
60
|
+
for (const file of files) {
|
|
61
|
+
const findings = session.analyzeFile(file.path, file.content, file.language);
|
|
62
|
+
allFindings.push(...findings);
|
|
63
|
+
}
|
|
64
|
+
const duration = Date.now() - startTime;
|
|
65
|
+
return {
|
|
66
|
+
findings: allFindings,
|
|
67
|
+
duration,
|
|
68
|
+
filesAnalyzed: files.length,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create analysis session with frozen snapshot
|
|
73
|
+
*/
|
|
74
|
+
export function createSession(config, policies) {
|
|
75
|
+
return new AnalysisSession(config, policies);
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analysis core index
|
|
3
|
+
* @description Core analysis engine exports
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
// Contract-based engine (recommended)
|
|
7
|
+
export { AnalysisEngineV1 } from './engine.contract.js';
|
|
8
|
+
// Legacy engine (backward compatibility)
|
|
9
|
+
export { analyze, createSession } from './engine.js';
|
|
10
|
+
// Discovery
|
|
11
|
+
export { discoverFiles, isValidProjectRoot, analyzeProjectTypes, } from './discovery.js';
|
|
12
|
+
// Orchestrator
|
|
13
|
+
export { runAnalysis, generateReport, saveReport, } from './orchestrator.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analysis Orchestrator
|
|
3
|
+
* Coordinates file discovery and AST parsing for complete project analysis
|
|
4
|
+
*/
|
|
5
|
+
import { promises as fs } from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { discoverFiles } from './discovery.js';
|
|
8
|
+
import { parseSource } from '../parser/unified-parser.js';
|
|
9
|
+
/**
|
|
10
|
+
* Generate unique analysis ID
|
|
11
|
+
*/
|
|
12
|
+
function generateAnalysisId() {
|
|
13
|
+
const timestamp = Date.now().toString(36);
|
|
14
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
15
|
+
return `analysis-${timestamp}-${random}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run complete project analysis
|
|
19
|
+
*/
|
|
20
|
+
export async function runAnalysis(options) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const id = generateAnalysisId();
|
|
23
|
+
// Step 1: Discover files
|
|
24
|
+
console.log('🔍 Discovering files...');
|
|
25
|
+
const discoveryOptions = {
|
|
26
|
+
rootDir: options.rootDir,
|
|
27
|
+
include: options.include,
|
|
28
|
+
exclude: options.exclude,
|
|
29
|
+
maxFileSize: options.maxFileSize,
|
|
30
|
+
};
|
|
31
|
+
const discovered = await discoverFiles(discoveryOptions);
|
|
32
|
+
console.log(` Found ${discovered.files.length} files (${(discovered.totalSize / 1024 / 1024).toFixed(2)} MB)`);
|
|
33
|
+
// Step 2: Parse each file
|
|
34
|
+
console.log('📝 Parsing source files...');
|
|
35
|
+
const files = [];
|
|
36
|
+
const errors = [];
|
|
37
|
+
let totalLines = 0;
|
|
38
|
+
let totalFunctions = 0;
|
|
39
|
+
let totalClasses = 0;
|
|
40
|
+
let totalImports = 0;
|
|
41
|
+
let totalExports = 0;
|
|
42
|
+
let totalComplexity = 0;
|
|
43
|
+
for (let i = 0; i < discovered.files.length; i++) {
|
|
44
|
+
const file = discovered.files[i];
|
|
45
|
+
// Progress indicator
|
|
46
|
+
if (i % 10 === 0 || i === discovered.files.length - 1) {
|
|
47
|
+
process.stdout.write(`\r ${i + 1}/${discovered.files.length} files...`);
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const parseStart = Date.now();
|
|
51
|
+
const source = await fs.readFile(file.path, 'utf-8');
|
|
52
|
+
const parseResult = parseSource(source, { filePath: file.path });
|
|
53
|
+
const duration = Date.now() - parseStart;
|
|
54
|
+
files.push({
|
|
55
|
+
file,
|
|
56
|
+
parseResult,
|
|
57
|
+
duration,
|
|
58
|
+
});
|
|
59
|
+
// Accumulate metrics
|
|
60
|
+
if (parseResult.success && parseResult.metrics) {
|
|
61
|
+
totalLines += parseResult.metrics.loc;
|
|
62
|
+
totalFunctions += parseResult.metrics.functions;
|
|
63
|
+
totalClasses += parseResult.metrics.classes;
|
|
64
|
+
totalImports += parseResult.metrics.imports;
|
|
65
|
+
totalExports += parseResult.metrics.exports;
|
|
66
|
+
totalComplexity += parseResult.metrics.complexity;
|
|
67
|
+
}
|
|
68
|
+
// Collect errors
|
|
69
|
+
if (!parseResult.success) {
|
|
70
|
+
errors.push({
|
|
71
|
+
file: file.relativePath,
|
|
72
|
+
error: parseResult.errors[0]?.message || 'Parse failed',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
errors.push({
|
|
78
|
+
file: file.relativePath,
|
|
79
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
console.log('\n✅ Analysis complete!');
|
|
84
|
+
// Calculate project type
|
|
85
|
+
const { analyzeProjectTypes } = await import('./discovery.js');
|
|
86
|
+
const projectType = analyzeProjectTypes(discovered.files);
|
|
87
|
+
const totalDuration = Date.now() - startTime;
|
|
88
|
+
const successfulParses = files.filter(f => f.parseResult.success).length;
|
|
89
|
+
return {
|
|
90
|
+
id,
|
|
91
|
+
timestamp: new Date().toISOString(),
|
|
92
|
+
rootDir: path.resolve(options.rootDir),
|
|
93
|
+
options,
|
|
94
|
+
summary: {
|
|
95
|
+
totalFiles: files.length,
|
|
96
|
+
successfulParses,
|
|
97
|
+
failedParses: files.length - successfulParses,
|
|
98
|
+
totalLines,
|
|
99
|
+
totalFunctions,
|
|
100
|
+
totalClasses,
|
|
101
|
+
totalImports,
|
|
102
|
+
totalExports,
|
|
103
|
+
averageComplexity: successfulParses > 0 ? Math.round(totalComplexity / successfulParses) : 0,
|
|
104
|
+
totalDuration,
|
|
105
|
+
},
|
|
106
|
+
files,
|
|
107
|
+
errors,
|
|
108
|
+
projectType,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Generate report from analysis result
|
|
113
|
+
*/
|
|
114
|
+
export function generateReport(result, format = 'json') {
|
|
115
|
+
switch (format) {
|
|
116
|
+
case 'json':
|
|
117
|
+
return {
|
|
118
|
+
id: result.id,
|
|
119
|
+
content: JSON.stringify(result, null, 2),
|
|
120
|
+
format: 'json',
|
|
121
|
+
};
|
|
122
|
+
case 'markdown':
|
|
123
|
+
return {
|
|
124
|
+
id: result.id,
|
|
125
|
+
content: generateMarkdownReport(result),
|
|
126
|
+
format: 'markdown',
|
|
127
|
+
};
|
|
128
|
+
case 'html':
|
|
129
|
+
return {
|
|
130
|
+
id: result.id,
|
|
131
|
+
content: generateHtmlReport(result),
|
|
132
|
+
format: 'html',
|
|
133
|
+
};
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(`Unknown format: ${format}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Generate markdown report
|
|
140
|
+
*/
|
|
141
|
+
function generateMarkdownReport(result) {
|
|
142
|
+
const { summary, projectType, errors } = result;
|
|
143
|
+
return `# Delta Analysis Report
|
|
144
|
+
|
|
145
|
+
**Project:** \`${result.rootDir}\`
|
|
146
|
+
**Generated:** ${new Date(result.timestamp).toLocaleString()}
|
|
147
|
+
**Analysis ID:** \`${result.id}\`
|
|
148
|
+
|
|
149
|
+
## Summary
|
|
150
|
+
|
|
151
|
+
| Metric | Value |
|
|
152
|
+
|--------|-------|
|
|
153
|
+
| Total Files | ${summary.totalFiles} |
|
|
154
|
+
| Successfully Parsed | ${summary.successfulParses} |
|
|
155
|
+
| Failed Parses | ${summary.failedParses} |
|
|
156
|
+
| Total Lines | ${summary.totalLines.toLocaleString()} |
|
|
157
|
+
| Functions | ${summary.totalFunctions.toLocaleString()} |
|
|
158
|
+
| Classes | ${summary.totalClasses.toLocaleString()} |
|
|
159
|
+
| Average Complexity | ${summary.averageComplexity} |
|
|
160
|
+
| Duration | ${(summary.totalDuration / 1000).toFixed(2)}s |
|
|
161
|
+
|
|
162
|
+
## Project Type
|
|
163
|
+
|
|
164
|
+
- **JavaScript:** ${projectType.hasJavaScript ? '✅' : '❌'}
|
|
165
|
+
- **TypeScript:** ${projectType.hasTypeScript ? '✅' : '❌'}
|
|
166
|
+
- **React:** ${projectType.hasReact ? '✅' : '❌'}
|
|
167
|
+
- **Vue:** ${projectType.hasVue ? '✅' : '❌'}
|
|
168
|
+
- **Svelte:** ${projectType.hasSvelte ? '✅' : '❌'}
|
|
169
|
+
- **Module Type:** ${projectType.isESM ? 'ESM' : 'CJS'}
|
|
170
|
+
|
|
171
|
+
## Errors
|
|
172
|
+
|
|
173
|
+
${errors.length === 0
|
|
174
|
+
? 'No errors encountered.'
|
|
175
|
+
: errors.map((e) => `- **${e.file}:** ${e.error}`).join('\n')}
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
*Generated by Delta Platform*
|
|
179
|
+
`;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Generate HTML report
|
|
183
|
+
*/
|
|
184
|
+
function generateHtmlReport(result) {
|
|
185
|
+
const { summary, projectType } = result;
|
|
186
|
+
return `<!DOCTYPE html>
|
|
187
|
+
<html>
|
|
188
|
+
<head>
|
|
189
|
+
<title>Delta Analysis Report</title>
|
|
190
|
+
<style>
|
|
191
|
+
body { font-family: system-ui, sans-serif; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
|
|
192
|
+
h1 { color: #333; }
|
|
193
|
+
table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
|
|
194
|
+
th, td { padding: 0.5rem; text-align: left; border-bottom: 1px solid #ddd; }
|
|
195
|
+
th { background: #f5f5f5; }
|
|
196
|
+
.success { color: green; }
|
|
197
|
+
.error { color: red; }
|
|
198
|
+
</style>
|
|
199
|
+
</head>
|
|
200
|
+
<body>
|
|
201
|
+
<h1>Delta Analysis Report</h1>
|
|
202
|
+
<p><strong>Project:</strong> <code>${result.rootDir}</code></p>
|
|
203
|
+
<p><strong>Generated:</strong> ${new Date(result.timestamp).toLocaleString()}</p>
|
|
204
|
+
|
|
205
|
+
<h2>Summary</h2>
|
|
206
|
+
<table>
|
|
207
|
+
<tr><th>Metric</th><th>Value</th></tr>
|
|
208
|
+
<tr><td>Total Files</td><td>${summary.totalFiles}</td></tr>
|
|
209
|
+
<tr><td>Successfully Parsed</td><td class="success">${summary.successfulParses}</td></tr>
|
|
210
|
+
<tr><td>Failed Parses</td><td class="error">${summary.failedParses}</td></tr>
|
|
211
|
+
<tr><td>Total Lines</td><td>${summary.totalLines.toLocaleString()}</td></tr>
|
|
212
|
+
<tr><td>Functions</td><td>${summary.totalFunctions.toLocaleString()}</td></tr>
|
|
213
|
+
<tr><td>Classes</td><td>${summary.totalClasses.toLocaleString()}</td></tr>
|
|
214
|
+
</table>
|
|
215
|
+
|
|
216
|
+
<h2>Project Type</h2>
|
|
217
|
+
<ul>
|
|
218
|
+
<li>TypeScript: ${projectType.hasTypeScript ? '✅' : '❌'}</li>
|
|
219
|
+
<li>React: ${projectType.hasReact ? '✅' : '❌'}</li>
|
|
220
|
+
<li>Vue: ${projectType.hasVue ? '✅' : '❌'}</li>
|
|
221
|
+
</ul>
|
|
222
|
+
|
|
223
|
+
<footer>
|
|
224
|
+
<hr>
|
|
225
|
+
<p><small>Generated by Delta Platform</small></p>
|
|
226
|
+
</footer>
|
|
227
|
+
</body>
|
|
228
|
+
</html>`;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Save report to file
|
|
232
|
+
*/
|
|
233
|
+
export async function saveReport(result, outputDir, format = 'json') {
|
|
234
|
+
const report = generateReport(result, format);
|
|
235
|
+
const extension = format === 'markdown' ? 'md' : format;
|
|
236
|
+
const filename = `${result.id}.${extension}`;
|
|
237
|
+
const filepath = path.join(outputDir, filename);
|
|
238
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
239
|
+
await fs.writeFile(filepath, report.content, 'utf-8');
|
|
240
|
+
return filepath;
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=orchestrator.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comparison engine - Core domain logic for code comparison
|
|
3
|
+
* @see docs/architecture/OVERVIEW.md
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Comparison engine
|
|
7
|
+
* Compares analysis results between versions or projects
|
|
8
|
+
*/
|
|
9
|
+
export class ComparisonEngine {
|
|
10
|
+
/**
|
|
11
|
+
* Compare two analysis results
|
|
12
|
+
* @param baseline - Baseline analysis result
|
|
13
|
+
* @param current - Current analysis result
|
|
14
|
+
* @returns Comparison result
|
|
15
|
+
*/
|
|
16
|
+
async compare(baseline, current) {
|
|
17
|
+
// Implementation placeholder
|
|
18
|
+
void baseline;
|
|
19
|
+
void current;
|
|
20
|
+
return {
|
|
21
|
+
similarities: 0,
|
|
22
|
+
differences: 0,
|
|
23
|
+
additions: 0,
|
|
24
|
+
deletions: 0,
|
|
25
|
+
score: 0,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=engine.js.map
|