devcompass 2.6.0 → 2.7.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.
@@ -1,25 +1,36 @@
1
1
  // src/utils/json-formatter.js
2
-
3
- /**
4
- * Format analysis results as JSON
5
- */
6
- function formatAsJson(alerts, unusedDeps, outdatedDeps, score, totalDeps, securityData, bundleSizes, licenses, predictiveWarnings = []) {
7
- const problematicLicenses = licenses.filter(l => l.type === 'restrictive' || l.type === 'unknown');
8
- const heavyPackages = bundleSizes.filter(p => p.size > 1024);
9
-
10
- return JSON.stringify({
2
+ function formatAsJson(
3
+ alerts,
4
+ unusedDeps,
5
+ outdatedDeps,
6
+ score,
7
+ totalDeps,
8
+ securityData,
9
+ bundleSizes,
10
+ licenses,
11
+ predictiveWarnings = [],
12
+ supplyChainWarnings = [],
13
+ licenseRiskData = {},
14
+ qualityData = {},
15
+ recommendations = []
16
+ ) {
17
+ const output = {
11
18
  version: require('../../package.json').version,
12
19
  timestamp: new Date().toISOString(),
13
20
  summary: {
14
21
  healthScore: score.total,
15
22
  totalDependencies: totalDeps,
16
23
  securityVulnerabilities: securityData.metadata.total,
24
+ supplyChainWarnings: supplyChainWarnings.length,
17
25
  ecosystemAlerts: alerts.length,
18
26
  predictiveWarnings: predictiveWarnings.length,
27
+ licenseRisks: licenseRiskData.warnings ? licenseRiskData.warnings.length : 0,
28
+ qualityIssues: qualityData.stats ?
29
+ (qualityData.stats.abandoned || 0) + (qualityData.stats.deprecated || 0) + (qualityData.stats.stale || 0) : 0,
19
30
  unusedDependencies: unusedDeps.length,
20
31
  outdatedPackages: outdatedDeps.length,
21
- heavyPackages: heavyPackages.length,
22
- licenseWarnings: problematicLicenses.length
32
+ heavyPackages: bundleSizes.filter(p => p.size > 1024).length,
33
+ licenseWarnings: licenses.filter(l => l.type === 'restrictive' || l.type === 'unknown').length
23
34
  },
24
35
  security: {
25
36
  total: securityData.metadata.total,
@@ -28,13 +39,62 @@ function formatAsJson(alerts, unusedDeps, outdatedDeps, score, totalDeps, securi
28
39
  moderate: securityData.metadata.moderate,
29
40
  low: securityData.metadata.low,
30
41
  vulnerabilities: securityData.vulnerabilities.map(v => ({
31
- package: v.package,
42
+ package: v.name,
32
43
  severity: v.severity,
33
44
  title: v.title,
34
- cve: v.cve,
45
+ cve: v.cve || null,
35
46
  fixAvailable: v.fixAvailable
36
47
  }))
37
48
  },
49
+ supplyChain: {
50
+ total: supplyChainWarnings.length,
51
+ critical: supplyChainWarnings.filter(w => w.severity === 'critical').length,
52
+ high: supplyChainWarnings.filter(w => w.severity === 'high').length,
53
+ medium: supplyChainWarnings.filter(w => w.severity === 'medium').length,
54
+ warnings: supplyChainWarnings.map(w => ({
55
+ package: w.package,
56
+ type: w.type,
57
+ severity: w.severity,
58
+ message: w.message,
59
+ recommendation: w.recommendation,
60
+ official: w.official || null
61
+ }))
62
+ },
63
+ licenseRisk: {
64
+ total: licenseRiskData.warnings ? licenseRiskData.warnings.length : 0,
65
+ projectLicense: licenseRiskData.projectLicense || 'MIT',
66
+ critical: licenseRiskData.warnings ? licenseRiskData.warnings.filter(w => w.severity === 'critical').length : 0,
67
+ high: licenseRiskData.warnings ? licenseRiskData.warnings.filter(w => w.severity === 'high').length : 0,
68
+ medium: licenseRiskData.warnings ? licenseRiskData.warnings.filter(w => w.severity === 'medium').length : 0,
69
+ warnings: licenseRiskData.warnings ? licenseRiskData.warnings.map(w => ({
70
+ package: w.package,
71
+ license: w.license,
72
+ severity: w.severity,
73
+ type: w.type,
74
+ issue: w.issue,
75
+ message: w.message,
76
+ recommendation: w.recommendation
77
+ })) : []
78
+ },
79
+ packageQuality: {
80
+ total: qualityData.results ? qualityData.results.length : 0,
81
+ healthy: qualityData.stats ? qualityData.stats.healthy : 0,
82
+ needsAttention: qualityData.stats ? qualityData.stats.needsAttention : 0,
83
+ stale: qualityData.stats ? qualityData.stats.stale : 0,
84
+ abandoned: qualityData.stats ? qualityData.stats.abandoned : 0,
85
+ deprecated: qualityData.stats ? qualityData.stats.deprecated : 0,
86
+ packages: qualityData.results ? qualityData.results.map(r => ({
87
+ package: r.package,
88
+ version: r.version,
89
+ healthScore: r.healthScore,
90
+ status: r.status,
91
+ severity: r.severity,
92
+ lastPublish: r.lastPublish,
93
+ daysSincePublish: r.daysSincePublish,
94
+ maintainerStatus: r.maintainerStatus,
95
+ deprecated: r.deprecated
96
+ })) : []
97
+ },
38
98
  ecosystemAlerts: alerts.map(alert => ({
39
99
  package: alert.package,
40
100
  version: alert.version,
@@ -51,8 +111,32 @@ function formatAsJson(alerts, unusedDeps, outdatedDeps, score, totalDeps, securi
51
111
  title: warning.title,
52
112
  description: warning.description,
53
113
  recommendation: warning.recommendation,
54
- githubData: warning.data
114
+ githubData: warning.data ? {
115
+ totalIssues: warning.data.totalIssues,
116
+ recentIssues: warning.data.recentIssues,
117
+ criticalIssues: warning.data.criticalIssues,
118
+ trend: warning.data.trend,
119
+ repoUrl: warning.data.repoUrl
120
+ } : null
55
121
  })),
122
+ recommendations: {
123
+ total: recommendations.length,
124
+ critical: recommendations.filter(r => r.priority.level === 1).length,
125
+ high: recommendations.filter(r => r.priority.level === 2).length,
126
+ medium: recommendations.filter(r => r.priority.level === 3).length,
127
+ low: recommendations.filter(r => r.priority.level === 4).length,
128
+ items: recommendations.map(r => ({
129
+ priority: r.priority.label,
130
+ category: r.category,
131
+ package: r.package || null,
132
+ issue: r.issue,
133
+ action: r.action,
134
+ command: r.command || null,
135
+ impact: r.impact,
136
+ reason: r.reason,
137
+ alternative: r.alternative || null
138
+ }))
139
+ },
56
140
  unusedDependencies: unusedDeps.map(dep => ({
57
141
  name: dep.name
58
142
  })),
@@ -63,25 +147,31 @@ function formatAsJson(alerts, unusedDeps, outdatedDeps, score, totalDeps, securi
63
147
  updateType: dep.versionsBehind
64
148
  })),
65
149
  bundleAnalysis: {
66
- heavyPackages: heavyPackages.map(pkg => ({
67
- name: pkg.name,
68
- size: pkg.sizeFormatted
69
- }))
150
+ heavyPackages: bundleSizes
151
+ .filter(pkg => pkg.size > 1024)
152
+ .map(pkg => ({
153
+ name: pkg.name,
154
+ size: pkg.sizeFormatted
155
+ }))
70
156
  },
71
157
  licenses: {
72
- warnings: problematicLicenses.map(pkg => ({
73
- package: pkg.package,
74
- license: pkg.license,
75
- type: pkg.type
76
- }))
158
+ warnings: licenses
159
+ .filter(l => l.type === 'restrictive' || l.type === 'unknown')
160
+ .map(l => ({
161
+ package: l.package,
162
+ license: l.license,
163
+ type: l.type
164
+ }))
77
165
  },
78
166
  scoreBreakdown: {
79
- unusedPenalty: score.breakdown.unusedPenalty,
80
- outdatedPenalty: score.breakdown.outdatedPenalty,
81
- alertsPenalty: score.breakdown.alertsPenalty,
82
- securityPenalty: score.breakdown.securityPenalty
167
+ unusedPenalty: score.unusedPenalty,
168
+ outdatedPenalty: score.outdatedPenalty,
169
+ alertsPenalty: score.alertsPenalty,
170
+ securityPenalty: score.securityPenalty
83
171
  }
84
- }, null, 2);
172
+ };
173
+
174
+ return JSON.stringify(output, null, 2);
85
175
  }
86
176
 
87
177
  module.exports = { formatAsJson };