From d30b79c0d5fa419c21171a7927ba1b30c467df19 Mon Sep 17 00:00:00 2001 From: Peter van der Zee Date: Tue, 4 Mar 2025 12:30:13 +0100 Subject: [PATCH] Cleanup output for fix command --- src/commands/info/cmd-info.ts | 8 +- src/commands/info/fetch-package-info.ts | 17 +++- src/commands/info/format-package-info.ts | 109 ++++++++++++----------- src/commands/info/get-package-info.ts | 48 ++++------ 4 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/commands/info/cmd-info.ts b/src/commands/info/cmd-info.ts index 79aa18b1b..fabf8ead3 100644 --- a/src/commands/info/cmd-info.ts +++ b/src/commands/info/cmd-info.ts @@ -52,6 +52,7 @@ async function run( parentName }) + const { all, json, markdown, strict } = cli.flags const [rawPkgName = ''] = cli.input if (!rawPkgName || cli.input.length > 1) { @@ -78,11 +79,10 @@ async function run( await getPackageInfo({ commandName: `${parentName} ${config.commandName}`, - includeAllIssues: Boolean(cli.flags['all']), - outputJson: Boolean(cli.flags['json']), - outputMarkdown: Boolean(cli.flags['markdown']), + includeAllIssues: Boolean(all), + outputKind: json ? 'json' : markdown ? 'markdown' : 'print', pkgName, pkgVersion, - strict: Boolean(cli.flags['strict']) + strict: Boolean(strict) }) } diff --git a/src/commands/info/fetch-package-info.ts b/src/commands/info/fetch-package-info.ts index 7001ffff1..7f64662e8 100644 --- a/src/commands/info/fetch-package-info.ts +++ b/src/commands/info/fetch-package-info.ts @@ -1,6 +1,5 @@ -import { Spinner } from '@socketsecurity/registry/lib/spinner' - import { PackageData } from './get-package-info' +import constants from '../../constants' import { getSeverityCount } from '../../utils/alert/severity' import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api' import { getPublicToken, setupSdk } from '../../utils/sdk' @@ -8,9 +7,17 @@ import { getPublicToken, setupSdk } from '../../utils/sdk' export async function fetchPackageInfo( pkgName: string, pkgVersion: string, - includeAllIssues: boolean, - spinner: Spinner + includeAllIssues: boolean ): Promise { + // Lazily access constants.spinner. + const { spinner } = constants + + spinner.start( + pkgVersion === 'latest' + ? `Looking up data for the latest version of ${pkgName}` + : `Looking up data for version ${pkgVersion} of ${pkgName}` + ) + const socketSdk = await setupSdk(getPublicToken()) const result = await handleApiCall( socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), @@ -42,6 +49,8 @@ export async function fetchPackageInfo( includeAllIssues ? undefined : 'high' ) + spinner?.successAndStop('Data fetched') + return { data: result.data, severityCount, diff --git a/src/commands/info/format-package-info.ts b/src/commands/info/format-package-info.ts index 8bb982fcf..ce8a8c8e2 100644 --- a/src/commands/info/format-package-info.ts +++ b/src/commands/info/format-package-info.ts @@ -1,10 +1,7 @@ -import process from 'node:process' - import colors from 'yoctocolors-cjs' import constants from '@socketsecurity/registry/lib/constants' import { logger } from '@socketsecurity/registry/lib/logger' -import { Spinner } from '@socketsecurity/registry/lib/spinner' import { PackageData } from './get-package-info' import { formatSeverityCount } from '../../utils/alert/severity' @@ -23,69 +20,73 @@ export function formatPackageInfo( { data, score, severityCount }: PackageData, { name, - outputJson, - outputMarkdown, + outputKind, pkgName, - pkgVersion, - strict + pkgVersion }: { includeAllIssues: boolean - outputJson: boolean - outputMarkdown: boolean + name: string + outputKind: 'json' | 'markdown' | 'print' pkgName: string pkgVersion: string - strict: boolean - } & { name: string }, - spinner: Spinner + } ): void { - if (outputJson) { + if (outputKind === 'json') { logger.log(JSON.stringify(data, undefined, 2)) + return + } + + if (outputKind === 'markdown') { + logger.log(`\n# Package report for ${pkgName}\n`) + logger.log('Package report card:\n') } else { - logger.log('\nPackage report card:') - const scoreResult = { - 'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100), - Maintenance: Math.floor(score.maintenance.score * 100), - Quality: Math.floor(score.quality.score * 100), - Vulnerabilities: Math.floor(score.vulnerability.score * 100), - License: Math.floor(score.license.score * 100) + logger.log(`\nPackage report card for ${pkgName}:\n`) + } + const scoreResult = { + 'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100), + Maintenance: Math.floor(score.maintenance.score * 100), + Quality: Math.floor(score.quality.score * 100), + Vulnerabilities: Math.floor(score.vulnerability.score * 100), + License: Math.floor(score.license.score * 100) + } + Object.entries(scoreResult).map(score => + logger.log(`- ${score[0]}: ${formatScore(score[1])}`) + ) + logger.log('\n') + + if (objectSome(severityCount)) { + if (outputKind === 'markdown') { + logger.log('# Issues\n') } - Object.entries(scoreResult).map(score => - logger.log(`- ${score[0]}: ${formatScore(score[1])}`) + logger.log( + `Package has these issues: ${formatSeverityCount(severityCount)}\n` ) - logger.log('\n') - if (objectSome(severityCount)) { - spinner[strict ? 'error' : 'success']( - `Package has these issues: ${formatSeverityCount(severityCount)}` - ) - formatPackageIssuesDetails(data, outputMarkdown) - } else { - spinner.successAndStop('Package has no issues') - } + formatPackageIssuesDetails(data, outputKind === 'markdown') + } else { + logger.log('Package has no issues') + } - const format = new ColorOrMarkdown(!!outputMarkdown) - const url = getSocketDevPackageOverviewUrl(NPM, pkgName, pkgVersion) + const format = new ColorOrMarkdown(outputKind === 'markdown') + const url = getSocketDevPackageOverviewUrl(NPM, pkgName, pkgVersion) - logger.log('\n') - if (pkgVersion === 'latest') { - logger.log( - `Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, { fallbackToUrl: true })}` - ) - } else { - logger.log( - `Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true })}` - ) - } - if (!outputMarkdown) { - logger.log( - colors.dim( - `\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output` - ) - ) - } + logger.log('\n') + if (pkgVersion === 'latest') { + logger.log( + `Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, { fallbackToUrl: true })}` + ) + } else { + logger.log( + `Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true })}` + ) } - - if (strict && objectSome(severityCount)) { - process.exit(1) + if (outputKind !== 'markdown') { + logger.log( + colors.dim( + `\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output` + ) + ) + } else { + logger.log('') } } @@ -118,7 +119,7 @@ function formatPackageIssuesDetails( {} ) - const format = new ColorOrMarkdown(!!outputMarkdown) + const format = new ColorOrMarkdown(outputMarkdown) for (const issue of Object.keys(uniqueIssues)) { const issueWithLink = format.hyperlink( `${uniqueIssues[issue]?.label}`, diff --git a/src/commands/info/get-package-info.ts b/src/commands/info/get-package-info.ts index 21c51a94f..45d37d5e1 100644 --- a/src/commands/info/get-package-info.ts +++ b/src/commands/info/get-package-info.ts @@ -1,6 +1,8 @@ +import process from 'node:process' + import { fetchPackageInfo } from './fetch-package-info' import { formatPackageInfo } from './format-package-info' -import constants from '../../constants' +import { objectSome } from '../../utils/objects' import type { SocketSdkAlert } from '../../utils/alert/severity' import type { SocketSdkReturnType } from '@socketsecurity/sdk' @@ -14,48 +16,36 @@ export interface PackageData { export async function getPackageInfo({ commandName, includeAllIssues, - outputJson, - outputMarkdown, + outputKind, pkgName, pkgVersion, strict }: { commandName: string includeAllIssues: boolean - outputJson: boolean - outputMarkdown: boolean + outputKind: 'json' | 'markdown' | 'print' pkgName: string pkgVersion: string strict: boolean }) { - // Lazily access constants.spinner. - const { spinner } = constants - - spinner.start( - pkgVersion === 'latest' - ? `Looking up data for the latest version of ${pkgName}` - : `Looking up data for version ${pkgVersion} of ${pkgName}` - ) - const packageData = await fetchPackageInfo( pkgName, pkgVersion, - includeAllIssues, - spinner + includeAllIssues ) + if (packageData) { - formatPackageInfo( - packageData, - { - name: commandName, - includeAllIssues, - outputJson, - outputMarkdown, - pkgName, - pkgVersion, - strict - }, - spinner - ) + formatPackageInfo(packageData, { + name: commandName, + includeAllIssues, + outputKind, + pkgName, + pkgVersion + }) + + if (strict && objectSome(packageData.severityCount)) { + // Let NodeJS exit gracefully but with exit(1) + process.exitCode = 1 + } } }