Skip to content

Commit 25ebd02

Browse files
committed
Merge branch 'main' into scan_v2
2 parents 400f558 + 11d718b commit 25ebd02

File tree

13 files changed

+273
-178
lines changed

13 files changed

+273
-178
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
"lint-staged": "lint-staged",
5858
"precommit": "lint-staged",
5959
"prepare": "husky",
60+
"bs": "npm run build:dist; npm exec socket --",
61+
"s": "npm exec socket --",
6062
"test": "run-s check test:*",
6163
"test:prepare": "cross-env VITEST=1 npm run build",
6264
"test:unit": "vitest --run",

src/commands/dependencies/find-dependencies.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ export async function findDependencies({
4848
return
4949
}
5050

51+
logger.log(
52+
'Request details: Offset:',
53+
offset,
54+
', limit:',
55+
limit,
56+
', is there more data after this?',
57+
result.data.end ? 'no' : 'yes'
58+
)
59+
5160
const options = {
5261
columns: [
5362
{ field: 'namespace', name: colors.cyan('Namespace') },

src/commands/diff-scan/cmd-diff-scan-get.ts

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ import { logger } from '@socketsecurity/registry/lib/logger'
44

55
import { getDiffScan } from './get-diff-scan'
66
import constants from '../../constants'
7-
import { commonFlags, outputFlags } from '../../flags'
8-
import { AuthError } from '../../utils/errors'
7+
import { commonFlags } from '../../flags'
98
import { meowOrExit } from '../../utils/meow-with-subcommands'
109
import { getFlagListOutput } from '../../utils/output-formatting'
11-
import { getDefaultToken } from '../../utils/sdk'
1210

1311
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
1412

@@ -20,36 +18,47 @@ const config: CliCommandConfig = {
2018
hidden: false,
2119
flags: {
2220
...commonFlags,
21+
after: {
22+
type: 'string',
23+
shortFlag: 'a',
24+
default: '',
25+
description: 'The full scan ID of the head scan'
26+
},
2327
before: {
2428
type: 'string',
2529
shortFlag: 'b',
2630
default: '',
2731
description: 'The full scan ID of the base scan'
2832
},
29-
after: {
30-
type: 'string',
31-
shortFlag: 'a',
32-
default: '',
33-
description: 'The full scan ID of the head scan'
33+
depth: {
34+
type: 'number',
35+
default: 2,
36+
description:
37+
'Max depth of JSON to display before truncating, use zero for no limit (without --json/--file)'
3438
},
35-
preview: {
39+
json: {
3640
type: 'boolean',
37-
shortFlag: 'p',
38-
default: true,
39-
description: 'A boolean flag to persist or not the diff scan result'
41+
shortFlag: 'j',
42+
default: false,
43+
description:
44+
'Output result as json. This can be big. Use --file to store it to disk without truncation.'
4045
},
4146
file: {
4247
type: 'string',
4348
shortFlag: 'f',
4449
default: '',
45-
description: 'Path to a local file where the output should be saved'
46-
},
47-
...outputFlags
50+
description:
51+
'Path to a local file where the output should be saved. Use `-` to force stdout.'
52+
}
4853
},
4954
help: (command, config) => `
5055
Usage
5156
$ ${command} <org slug> --before=<before> --after=<after>
5257
58+
This command displays the package changes between two scans. The full output
59+
can be pretty large depending on the size of your repo and time range. It is
60+
best stored to disk to be further analyzed by other tools.
61+
5362
Options
5463
${getFlagListOutput(config.flags, 6)}
5564
@@ -88,6 +97,7 @@ async function run(
8897
logger.error(`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
8998
- Specify a before and after full scan ID ${!before && !after ? colors.red('(missing before and after!)') : !before ? colors.red('(missing before!)') : !after ? colors.red('(missing after!)') : colors.green('(ok)')}\n
9099
- To get full scans IDs, you can run the command "socket scan list <your org slug>".
100+
The args are expecting a full \`aaa0aa0a-aaaa-0000-0a0a-0000000a00a0\` ID.\n
91101
- Org name as the first argument ${!orgSlug ? colors.red('(missing!)') : colors.green('(ok)')}\n`)
92102
return
93103
}
@@ -97,23 +107,12 @@ async function run(
97107
return
98108
}
99109

100-
const apiToken = getDefaultToken()
101-
if (!apiToken) {
102-
throw new AuthError(
103-
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
104-
)
105-
}
106-
107-
await getDiffScan(
108-
{
109-
outputJson: Boolean(cli.flags['json']),
110-
outputMarkdown: Boolean(cli.flags['markdown']),
111-
before,
112-
after,
113-
preview: Boolean(cli.flags['preview']),
114-
orgSlug,
115-
file: String(cli.flags['file'] || '')
116-
},
117-
apiToken
118-
)
110+
await getDiffScan({
111+
outputJson: Boolean(cli.flags['json']),
112+
before,
113+
after,
114+
depth: Number(cli.flags['depth']),
115+
orgSlug,
116+
file: String(cli.flags['file'] || '')
117+
})
119118
}

src/commands/diff-scan/cmd-diff-scan.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ const description = 'Diff scans related commands'
77

88
export const cmdDiffScan: CliSubcommand = {
99
description,
10+
// Hidden because it was broken all this time (nobody could be using it)
11+
// and we're not sure if it's useful to anyone in its current state.
12+
// Until we do, we'll hide this to keep the help tidier.
13+
// And later, we may simply move this under `scan`, anyways.
14+
hidden: true,
1015
async run(argv, importMeta, { parentName }) {
1116
await meowWithSubcommands(
1217
{

src/commands/diff-scan/get-diff-scan.ts

Lines changed: 103 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,71 @@ import util from 'node:util'
44
import colors from 'yoctocolors-cjs'
55

66
import { logger } from '@socketsecurity/registry/lib/logger'
7+
import { SocketSdkReturnType } from '@socketsecurity/sdk'
78

89
import constants from '../../constants'
9-
import { handleAPIError, queryAPI } from '../../utils/api'
10+
import { handleAPIError, handleApiCall, queryAPI } from '../../utils/api'
11+
import { AuthError } from '../../utils/errors'
12+
import { getDefaultToken } from '../../utils/sdk'
1013

11-
export async function getDiffScan(
12-
{
14+
export async function getDiffScan({
15+
after,
16+
before,
17+
depth,
18+
file,
19+
orgSlug,
20+
outputJson
21+
}: {
22+
after: string
23+
before: string
24+
depth: number
25+
file: string
26+
orgSlug: string
27+
outputJson: boolean
28+
}): Promise<void> {
29+
const apiToken = getDefaultToken()
30+
if (!apiToken) {
31+
throw new AuthError(
32+
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
33+
)
34+
}
35+
36+
await getDiffScanWithToken({
1337
after,
1438
before,
39+
depth,
1540
file,
1641
orgSlug,
17-
outputJson
18-
}: {
19-
outputJson: boolean
20-
outputMarkdown: boolean
21-
before: string
22-
after: string
23-
preview: boolean
24-
orgSlug: string
25-
file: string
26-
},
42+
outputJson,
43+
apiToken
44+
})
45+
}
46+
export async function getDiffScanWithToken({
47+
after,
48+
apiToken,
49+
before,
50+
depth,
51+
file,
52+
orgSlug,
53+
outputJson
54+
}: {
55+
after: string
2756
apiToken: string
28-
): Promise<void> {
57+
depth: number
58+
before: string
59+
file: string
60+
orgSlug: string
61+
outputJson: boolean
62+
}): Promise<void> {
2963
// Lazily access constants.spinner.
3064
const { spinner } = constants
3165

3266
spinner.start('Getting diff scan...')
3367

3468
const response = await queryAPI(
35-
`${orgSlug}/full-scans/diff?before=${before}&after=${after}&preview`,
69+
`orgs/${orgSlug}/full-scans/diff?before=${encodeURIComponent(before)}&after=${encodeURIComponent(after)}`,
3670
apiToken
3771
)
38-
const data = await response.json()
3972

4073
if (!response.ok) {
4174
const err = await handleAPIError(response.status)
@@ -45,34 +78,69 @@ export async function getDiffScan(
4578
return
4679
}
4780

81+
const result = await handleApiCall(
82+
(await response.json()) as Promise<
83+
SocketSdkReturnType<'GetOrgDiffScan'>['data']
84+
>,
85+
'Deserializing json'
86+
)
87+
4888
spinner.stop()
4989

50-
if (file && !outputJson) {
51-
fs.writeFile(file, JSON.stringify(data), err => {
52-
err
53-
? logger.error(err)
54-
: logger.log(`Data successfully written to ${file}`)
55-
})
56-
return
57-
}
90+
const dashboardUrl = (result as any)?.['diff_report_url']
91+
const dashboardMessage = dashboardUrl
92+
? `\n View this diff scan in the Socket dashboard: ${colors.cyan(dashboardUrl)}`
93+
: ''
94+
95+
// When forcing json, or dumping to file, serialize to string such that it
96+
// won't get truncated. The only way to dump the full raw JSON to stdout is
97+
// to use `--json --file -` (the dash is a standard notation for stdout)
98+
if (outputJson || file) {
99+
let json
100+
try {
101+
json = JSON.stringify(result, null, 2)
102+
} catch (e) {
103+
// Most likely caused by a circular reference (or OOM)
104+
logger.error('There was a problem converting the data to JSON')
105+
process.exitCode = 1
106+
return
107+
}
108+
109+
if (file && file !== '-') {
110+
logger.log(`Writing json to \`${file}\``)
111+
fs.writeFile(file, JSON.stringify(result, null, 2), err => {
112+
if (err) {
113+
logger.error(`Writing to \`${file}\` failed...`)
114+
logger.error(err)
115+
} else {
116+
logger.log(`Data successfully written to \`${file}\``)
117+
}
118+
logger.error(dashboardMessage)
119+
})
120+
} else {
121+
// TODO: expose different method for writing to stderr when simply dodging stdout
122+
logger.error(`\n Diff scan result: \n`)
123+
logger.log(json)
124+
logger.error(dashboardMessage)
125+
}
58126

59-
if (outputJson) {
60-
logger.log(`\n Diff scan result: \n`)
61-
logger.log(
62-
util.inspect(data, { showHidden: false, depth: null, colors: true })
63-
)
64-
logger.log(
65-
`\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`
66-
)
67127
return
68128
}
69129

130+
// In this case neither the --json nor the --file flag was passed
131+
// Dump the JSON to CLI and let NodeJS deal with truncation
132+
70133
logger.log('Diff scan result:')
71-
logger.log(data)
72134
logger.log(
73-
`\n 📝 To display the detailed report in the terminal, use the --json flag \n`
135+
util.inspect(result, {
136+
showHidden: false,
137+
depth: depth > 0 ? depth : null,
138+
colors: true,
139+
maxArrayLength: null
140+
})
74141
)
75142
logger.log(
76-
`\n View this diff scan in the Socket dashboard: ${colors.cyan((data as any)?.['diff_report_url'])}`
143+
`\n 📝 To display the detailed report in the terminal, use the --json flag \n`
77144
)
145+
logger.log(dashboardMessage)
78146
}

src/commands/info/cmd-info.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ async function run(
5252
parentName
5353
})
5454

55+
const { all, json, markdown, strict } = cli.flags
5556
const [rawPkgName = ''] = cli.input
5657

5758
if (!rawPkgName || cli.input.length > 1) {
@@ -78,11 +79,10 @@ async function run(
7879

7980
await getPackageInfo({
8081
commandName: `${parentName} ${config.commandName}`,
81-
includeAllIssues: Boolean(cli.flags['all']),
82-
outputJson: Boolean(cli.flags['json']),
83-
outputMarkdown: Boolean(cli.flags['markdown']),
82+
includeAllIssues: Boolean(all),
83+
outputKind: json ? 'json' : markdown ? 'markdown' : 'print',
8484
pkgName,
8585
pkgVersion,
86-
strict: Boolean(cli.flags['strict'])
86+
strict: Boolean(strict)
8787
})
8888
}

src/commands/info/fetch-package-info.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
import { Spinner } from '@socketsecurity/registry/lib/spinner'
2-
31
import { PackageData } from './get-package-info'
2+
import constants from '../../constants'
43
import { getSeverityCount } from '../../utils/alert/severity'
54
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'
65
import { getPublicToken, setupSdk } from '../../utils/sdk'
76

87
export async function fetchPackageInfo(
98
pkgName: string,
109
pkgVersion: string,
11-
includeAllIssues: boolean,
12-
spinner: Spinner
10+
includeAllIssues: boolean
1311
): Promise<void | PackageData> {
12+
// Lazily access constants.spinner.
13+
const { spinner } = constants
14+
15+
spinner.start(
16+
pkgVersion === 'latest'
17+
? `Looking up data for the latest version of ${pkgName}`
18+
: `Looking up data for version ${pkgVersion} of ${pkgName}`
19+
)
20+
1421
const socketSdk = await setupSdk(getPublicToken())
1522
const result = await handleApiCall(
1623
socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion),
@@ -42,6 +49,8 @@ export async function fetchPackageInfo(
4249
includeAllIssues ? undefined : 'high'
4350
)
4451

52+
spinner?.successAndStop('Data fetched')
53+
4554
return {
4655
data: result.data,
4756
severityCount,

0 commit comments

Comments
 (0)