Skip to content

Commit d0626a9

Browse files
Merge pull request #93 from SocketDev/cg/renderIssuesSocketInfo
Render issues when running `socket info`
2 parents edf65a6 + 1a0d214 commit d0626a9

File tree

1 file changed

+49
-19
lines changed

1 file changed

+49
-19
lines changed

lib/commands/info/index.js

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ export const info = {
2020
const name = parentName + ' info'
2121

2222
const input = setupCommand(name, info.description, argv, importMeta)
23-
const packageData = input && await fetchPackageData(input.pkgName, input.pkgVersion, input)
24-
25-
if (packageData) {
26-
formatPackageDataOutput(packageData, { name, ...input })
23+
if (input) {
24+
const spinner = ora(`Looking up data for version ${input.pkgVersion} of ${input.pkgName}\n`).start()
25+
const packageData = await fetchPackageData(input.pkgName, input.pkgVersion, input, spinner)
26+
if (packageData) {
27+
formatPackageDataOutput(packageData, { name, ...input }, spinner)
28+
}
2729
}
2830
}
2931
}
@@ -121,12 +123,12 @@ function setupCommand (name, description, argv, importMeta) {
121123
/**
122124
* @param {string} pkgName
123125
* @param {string} pkgVersion
124-
* @param {Pick<CommandContext, 'includeAllIssues' | 'strict'>} context
126+
* @param {Pick<CommandContext, 'includeAllIssues'>} context
127+
* @param {import('ora').Ora} spinner
125128
* @returns {Promise<void|PackageData>}
126129
*/
127-
async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict }) {
130+
async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues }, spinner) {
128131
const socketSdk = await setupSdk(getDefaultKey() || FREE_API_KEY)
129-
const spinner = ora(`Looking up data for version ${pkgVersion} of ${pkgName}`).start()
130132
const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package')
131133
const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score')
132134

@@ -139,16 +141,8 @@ async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict
139141
}
140142

141143
// Conclude the status of the API call
142-
143144
const severityCount = getSeverityCount(result.data, includeAllIssues ? undefined : 'high')
144145

145-
if (objectSome(severityCount)) {
146-
const issueSummary = formatSeverityCount(severityCount)
147-
spinner[strict ? 'fail' : 'succeed'](`Package has these issues: ${issueSummary}`)
148-
} else {
149-
spinner.succeed('Package has no issues')
150-
}
151-
152146
return {
153147
data: result.data,
154148
severityCount,
@@ -159,14 +153,14 @@ async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict
159153
/**
160154
* @param {PackageData} packageData
161155
* @param {{ name: string } & CommandContext} context
156+
* @param {import('ora').Ora} spinner
162157
* @returns {void}
163158
*/
164-
function formatPackageDataOutput ({ data, severityCount, score }, { name, outputJson, outputMarkdown, pkgName, pkgVersion, strict }) {
159+
function formatPackageDataOutput ({ data, severityCount, score }, { name, outputJson, outputMarkdown, pkgName, pkgVersion, strict }, spinner) {
165160
if (outputJson) {
166161
console.log(JSON.stringify(data, undefined, 2))
167162
} else {
168-
console.log('\nPackage report card:\n')
169-
163+
console.log('\nPackage report card:')
170164
const scoreResult = {
171165
'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),
172166
'Maintenance': Math.floor(score.maintenance.score * 100),
@@ -176,9 +170,20 @@ async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict
176170
}
177171
Object.entries(scoreResult).map(score => console.log(`- ${score[0]}: ${formatScore(score[1])}`))
178172

173+
// Package issues list
174+
if (objectSome(severityCount)) {
175+
const issueSummary = formatSeverityCount(severityCount)
176+
console.log('\n')
177+
spinner[strict ? 'fail' : 'succeed'](`Package has these issues: ${issueSummary}`)
178+
formatPackageIssuesDetails(data)
179+
} else {
180+
console.log('\n')
181+
spinner.succeed('Package has no issues')
182+
}
183+
184+
// Link to issues list
179185
const format = new ChalkOrMarkdown(!!outputMarkdown)
180186
const url = `https://socket.dev/npm/package/${pkgName}/overview/${pkgVersion}`
181-
182187
console.log('\nDetailed info on socket.dev: ' + format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true }))
183188
if (!outputMarkdown) {
184189
console.log(chalk.dim('\nOr rerun', chalk.italic(name), 'using the', chalk.italic('--json'), 'flag to get full JSON output'))
@@ -190,6 +195,31 @@ async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict
190195
}
191196
}
192197

198+
/**
199+
* @param {import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>["data"]} packageData
200+
* @returns {void[]}
201+
*/
202+
function formatPackageIssuesDetails (packageData) {
203+
const issueDetails = packageData.filter(d => d.value?.severity === 'high' || d.value?.severity === 'critical')
204+
const uniqueIssues = issueDetails.reduce((/** @type {{ [key: string]: number }} */ acc, issue) => {
205+
const { type } = issue
206+
if (type) {
207+
if (!acc[type]) {
208+
acc[type] = 1
209+
} else {
210+
acc[type]++
211+
}
212+
}
213+
return acc
214+
}, {})
215+
return Object.keys(uniqueIssues).map(issue => {
216+
if (uniqueIssues[issue] === 1) {
217+
return console.log(`- ${issue}`)
218+
}
219+
return console.log(`- ${issue}: ${uniqueIssues[issue]}`)
220+
})
221+
}
222+
193223
/**
194224
* @param {number} score
195225
* @returns {string}

0 commit comments

Comments
 (0)