Skip to content

Commit fd61bc9

Browse files
Pelle Wessmanvoxpelli
authored andcommitted
Adds --strict and --all to the commands
1 parent 2b27c01 commit fd61bc9

File tree

6 files changed

+241
-71
lines changed

6 files changed

+241
-71
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ socket report view QXU8PmK7LfH608RAwfIKdbcHgwEd_ZeWJ9QEGv05FJUQ
3636
* `--json` - outputs result as json which you can then pipe into [`jq`](https://stedolan.github.io/jq/) and other tools
3737
* `--markdown` - outputs result as markdown which you can then copy into an issue, PR or even chat
3838

39+
## Strictness flags
40+
41+
* `--all` - by default only `high` and `critical` issues are included, by setting this flag all issues will be included
42+
* `--strict` - when set, exits with an error code if any issues were found
43+
3944
### Other flags
4045

4146
* `--dry-run` - like all CLI tools that perform an action should have, we have a dry run flag. Eg. `socket report create` supports running the command without actually uploading anything

lib/commands/info/index.js

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import ora from 'ora'
77
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
88
import { ChalkOrMarkdown } from '../../utils/chalk-markdown.js'
99
import { InputError } from '../../utils/errors.js'
10-
import { getSeveritySummary } from '../../utils/format-issues.js'
10+
import { getSeverityCount, formatSeverityCount } from '../../utils/format-issues.js'
1111
import { printFlagList } from '../../utils/formatting.js'
12+
import { objectSome } from '../../utils/misc.js'
1213
import { setupSdk } from '../../utils/sdk.js'
1314

1415
/** @type {import('../../utils/meow-with-subcommands').CliSubcommand} */
@@ -18,32 +19,44 @@ export const info = {
1819
const name = parentName + ' info'
1920

2021
const input = setupCommand(name, info.description, argv, importMeta)
21-
const result = input && await fetchPackageData(input.pkgName, input.pkgVersion)
22+
const packageData = input && await fetchPackageData(input.pkgName, input.pkgVersion, input)
2223

23-
if (result) {
24-
formatPackageDataOutput(result.data, { name, ...input })
24+
if (packageData) {
25+
formatPackageDataOutput(packageData, { name, ...input })
2526
}
2627
}
2728
}
2829

2930
// Internal functions
3031

32+
/**
33+
* @typedef CommandContext
34+
* @property {boolean} includeAllIssues
35+
* @property {boolean} outputJson
36+
* @property {boolean} outputMarkdown
37+
* @property {string} pkgName
38+
* @property {string} pkgVersion
39+
* @property {boolean} strict
40+
*/
41+
3142
/**
3243
* @param {string} name
3344
* @param {string} description
3445
* @param {readonly string[]} argv
3546
* @param {ImportMeta} importMeta
36-
* @returns {void|{ outputJson: boolean, outputMarkdown: boolean, pkgName: string, pkgVersion: string }}
47+
* @returns {void|CommandContext}
3748
*/
38-
function setupCommand (name, description, argv, importMeta) {
49+
function setupCommand (name, description, argv, importMeta) {
3950
const cli = meow(`
4051
Usage
4152
$ ${name} <name>
4253
4354
Options
4455
${printFlagList({
56+
'--all': 'Include all issues',
4557
'--json': 'Output result as json',
4658
'--markdown': 'Output result as markdown',
59+
'--strict': 'Exits with an error code if any matching issues are found',
4760
}, 6)}
4861
4962
Examples
@@ -54,6 +67,10 @@ export const info = {
5467
description,
5568
importMeta,
5669
flags: {
70+
all: {
71+
type: 'boolean',
72+
default: false,
73+
},
5774
json: {
5875
type: 'boolean',
5976
alias: 'j',
@@ -64,12 +81,18 @@ export const info = {
6481
alias: 'm',
6582
default: false,
6683
},
84+
strict: {
85+
type: 'boolean',
86+
default: false,
87+
},
6788
}
6889
})
6990

7091
const {
92+
all: includeAllIssues,
7193
json: outputJson,
7294
markdown: outputMarkdown,
95+
strict,
7396
} = cli.flags
7497

7598
if (cli.input.length > 1) {
@@ -97,19 +120,28 @@ export const info = {
97120
}
98121

99122
return {
123+
includeAllIssues,
100124
outputJson,
101125
outputMarkdown,
102126
pkgName,
103-
pkgVersion
127+
pkgVersion,
128+
strict,
104129
}
105130
}
106131

132+
/**
133+
* @typedef PackageData
134+
* @property {import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>["data"]} data
135+
* @property {Record<import('../../utils/format-issues').SocketIssue['severity'], number>} severityCount
136+
*/
137+
107138
/**
108139
* @param {string} pkgName
109140
* @param {string} pkgVersion
110-
* @returns {Promise<void|import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>>}
141+
* @param {Pick<CommandContext, 'includeAllIssues' | 'strict'>} context
142+
* @returns {Promise<void|PackageData>}
111143
*/
112-
async function fetchPackageData (pkgName, pkgVersion) {
144+
async function fetchPackageData (pkgName, pkgVersion, { includeAllIssues, strict }) {
113145
const socketSdk = await setupSdk()
114146
const spinner = ora(`Looking up data for version ${pkgVersion} of ${pkgName}`).start()
115147
const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), spinner, 'looking up package')
@@ -120,32 +152,40 @@ async function fetchPackageData (pkgName, pkgVersion) {
120152

121153
// Conclude the status of the API call
122154

123-
const issueSummary = getSeveritySummary(result.data)
124-
spinner.succeed(`Found ${issueSummary || 'no'} issues for version ${pkgVersion} of ${pkgName}`)
155+
const severityCount = getSeverityCount(result.data, includeAllIssues ? undefined : 'high')
156+
157+
if (objectSome(severityCount)) {
158+
const issueSummary = formatSeverityCount(severityCount)
159+
spinner[strict ? 'fail' : 'succeed'](`Package has these issues: ${issueSummary}`)
160+
} else {
161+
spinner.succeed('Package has no issues')
162+
}
125163

126-
return result
164+
return {
165+
data: result.data,
166+
severityCount,
167+
}
127168
}
128169

129170
/**
130-
* @param {import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>["data"]} data
131-
* @param {{ name: string, outputJson: boolean, outputMarkdown: boolean, pkgName: string, pkgVersion: string }} context
171+
* @param {PackageData} packageData
172+
* @param {{ name: string } & CommandContext} context
132173
* @returns {void}
133174
*/
134-
function formatPackageDataOutput (data, { name, outputJson, outputMarkdown, pkgName, pkgVersion }) {
135-
// If JSON, output and return...
136-
175+
function formatPackageDataOutput ({ data, severityCount }, { name, outputJson, outputMarkdown, pkgName, pkgVersion, strict }) {
137176
if (outputJson) {
138177
console.log(JSON.stringify(data, undefined, 2))
139-
return
140-
}
141-
142-
// ...else do the CLI / Markdown output dance
178+
} else {
179+
const format = new ChalkOrMarkdown(!!outputMarkdown)
180+
const url = `https://socket.dev/npm/package/${pkgName}/overview/${pkgVersion}`
143181

144-
const format = new ChalkOrMarkdown(!!outputMarkdown)
145-
const url = `https://socket.dev/npm/package/${pkgName}/overview/${pkgVersion}`
182+
console.log('\nDetailed info on socket.dev: ' + format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true }))
183+
if (!outputMarkdown) {
184+
console.log(chalk.dim('\nOr rerun', chalk.italic(name), 'using the', chalk.italic('--json'), 'flag to get full JSON output'))
185+
}
186+
}
146187

147-
console.log('\nDetailed info on socket.dev: ' + format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true }))
148-
if (!outputMarkdown) {
149-
console.log(chalk.dim('\nOr rerun', chalk.italic(name), 'using the', chalk.italic('--json'), 'flag to get full JSON output'))
188+
if (strict && objectSome(severityCount)) {
189+
process.exit(1)
150190
}
151191
}

lib/commands/report/create.js

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,22 @@ export const create = {
2929
cwd,
3030
debugLog,
3131
dryRun,
32+
includeAllIssues,
3233
outputJson,
3334
outputMarkdown,
3435
packagePaths,
36+
strict,
3537
view,
3638
} = input
3739

3840
const result = input && await createReport(packagePaths, { cwd, debugLog, dryRun })
3941

4042
if (result && view) {
4143
const reportId = result.data.id
42-
const reportResult = input && await fetchReportData(reportId)
44+
const reportData = input && await fetchReportData(reportId, { includeAllIssues, strict })
4345

44-
if (reportResult) {
45-
formatReportDataOutput(reportResult.data, { name, outputJson, outputMarkdown, reportId })
46+
if (reportData) {
47+
formatReportDataOutput(reportData, { includeAllIssues, name, outputJson, outputMarkdown, reportId, strict })
4648
}
4749
} else if (result) {
4850
formatReportCreationOutput(result.data, { outputJson, outputMarkdown })
@@ -53,12 +55,25 @@ export const create = {
5355

5456
// Internal functions
5557

58+
/**
59+
* @typedef CommandContext
60+
* @property {string} cwd
61+
* @property {typeof console.error} debugLog
62+
* @property {boolean} dryRun
63+
* @property {boolean} includeAllIssues
64+
* @property {boolean} outputJson
65+
* @property {boolean} outputMarkdown
66+
* @property {string[]} packagePaths
67+
* @property {boolean} strict
68+
* @property {boolean} view
69+
*/
70+
5671
/**
5772
* @param {string} name
5873
* @param {string} description
5974
* @param {readonly string[]} argv
6075
* @param {ImportMeta} importMeta
61-
* @returns {Promise<void|{ cwd: string, debugLog: typeof console.error, dryRun: boolean, outputJson: boolean, outputMarkdown: boolean, packagePaths: string[], view: boolean }>}
76+
* @returns {Promise<void|CommandContext>}
6277
*/
6378
async function setupCommand (name, description, argv, importMeta) {
6479
const cli = meow(`
@@ -67,10 +82,12 @@ async function setupCommand (name, description, argv, importMeta) {
6782
6883
Options
6984
${printFlagList({
85+
'--all': 'Include all issues',
7086
'--debug': 'Output debug information',
7187
'--dry-run': 'Only output what will be done without actually doing it',
7288
'--json': 'Output result as json',
7389
'--markdown': 'Output result as markdown',
90+
'--strict': 'Exits with an error code if any matching issues are found',
7491
'--view': 'Will wait for and return the created report'
7592
}, 6)}
7693
@@ -84,6 +101,10 @@ async function setupCommand (name, description, argv, importMeta) {
84101
description,
85102
importMeta,
86103
flags: {
104+
all: {
105+
type: 'boolean',
106+
default: false,
107+
},
87108
debug: {
88109
type: 'boolean',
89110
alias: 'd',
@@ -103,6 +124,10 @@ async function setupCommand (name, description, argv, importMeta) {
103124
alias: 'm',
104125
default: false,
105126
},
127+
strict: {
128+
type: 'boolean',
129+
default: false,
130+
},
106131
view: {
107132
type: 'boolean',
108133
alias: 'v',
@@ -112,9 +137,11 @@ async function setupCommand (name, description, argv, importMeta) {
112137
})
113138

114139
const {
140+
all: includeAllIssues,
115141
dryRun,
116142
json: outputJson,
117143
markdown: outputMarkdown,
144+
strict,
118145
view,
119146
} = cli.flags
120147

@@ -132,16 +159,18 @@ async function setupCommand (name, description, argv, importMeta) {
132159
cwd,
133160
debugLog,
134161
dryRun,
162+
includeAllIssues,
135163
outputJson,
136164
outputMarkdown,
137165
packagePaths,
166+
strict,
138167
view,
139168
}
140169
}
141170

142171
/**
143172
* @param {string[]} packagePaths
144-
* @param {{ cwd: string, debugLog: typeof console.error, dryRun: boolean }} context
173+
* @param {Pick<CommandContext, 'cwd' | 'debugLog' | 'dryRun'>} context
145174
* @returns {Promise<void|import('@socketsecurity/sdk').SocketSdkReturnType<'createReport'>>}
146175
*/
147176
async function createReport (packagePaths, { cwd, debugLog, dryRun }) {
@@ -168,7 +197,7 @@ async function createReport (packagePaths, { cwd, debugLog, dryRun }) {
168197

169198
/**
170199
* @param {import('@socketsecurity/sdk').SocketSdkReturnType<'createReport'>["data"]} data
171-
* @param {{ outputJson: boolean, outputMarkdown: boolean }} context
200+
* @param {Pick<CommandContext, 'outputJson' | 'outputMarkdown'>} context
172201
* @returns {void}
173202
*/
174203
function formatReportCreationOutput (data, { outputJson, outputMarkdown }) {

0 commit comments

Comments
 (0)