Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@socketsecurity/cli

Package Overview
Dependencies
Maintainers
3
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@socketsecurity/cli - npm Package Compare versions

Comparing version 0.1.2 to 0.2.0

lib/commands/report/view.js

112

lib/commands/info/index.js

@@ -6,16 +6,35 @@ /* eslint-disable no-console */

import ora from 'ora'
import { ErrorWithCause } from 'pony-cause'
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
import { ChalkOrMarkdown } from '../../utils/chalk-markdown.js'
import { AuthError, InputError } from '../../utils/errors.js'
import { InputError } from '../../utils/errors.js'
import { getSeveritySummary } from '../../utils/format-issues.js'
import { printFlagList } from '../../utils/formatting.js'
import { stringJoinWithSeparateFinalSeparator } from '../../utils/misc.js'
import { setupSdk } from '../../utils/sdk.js'
const description = 'Look up info regarding a package'
/** @type {import('../../utils/meow-with-subcommands').CliSubcommand} */
export const info = {
description: 'Look up info regarding a package',
async run (argv, importMeta, { parentName }) {
const name = parentName + ' info'
/** @type {import('../../utils/meow-with-subcommands').CliSubcommandRun} */
const run = async (argv, importMeta, { parentName }) => {
const name = parentName + ' info'
const input = setupCommand(name, info.description, argv, importMeta)
const result = input && await fetchPackageData(input.pkgName, input.pkgVersion)
if (result) {
formatPackageDataOutput(result.data, { name, ...input })
}
}
}
// Internal functions
/**
* @param {string} name
* @param {string} description
* @param {readonly string[]} argv
* @param {ImportMeta} importMeta
* @returns {void|{ outputJson: boolean, outputMarkdown: boolean, pkgName: string, pkgVersion: string }}
*/
function setupCommand (name, description, argv, importMeta) {
const cli = meow(`

@@ -27,3 +46,2 @@ Usage

${printFlagList({
'--debug': 'Output debug information',
'--json': 'Output result as json',

@@ -41,7 +59,2 @@ '--markdown': 'Output result as markdown',

flags: {
debug: {
type: 'boolean',
alias: 'd',
default: false,
},
json: {

@@ -89,51 +102,40 @@ type: 'boolean',

return {
outputJson,
outputMarkdown,
pkgName,
pkgVersion
}
}
/**
* @param {string} pkgName
* @param {string} pkgVersion
* @returns {Promise<void|import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>>}
*/
async function fetchPackageData (pkgName, pkgVersion) {
const socketSdk = await setupSdk()
const spinner = ora(`Looking up data for version ${pkgVersion} of ${pkgName}`).start()
const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), spinner, 'looking up package')
/** @type {Awaited<ReturnType<import('@socketsecurity/sdk').SocketSdk["getIssuesByNPMPackage"]>>} */
let result
try {
result = await socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion)
} catch (cause) {
spinner.fail()
throw new ErrorWithCause('Failed to look up package', { cause })
}
if (result.success === false) {
if (result.status === 401 || result.status === 403) {
spinner.stop()
throw new AuthError(result.error.message)
}
spinner.fail(chalk.white.bgRed('API returned an error:') + ' ' + result.error.message)
process.exit(1)
return handleUnsuccessfulApiResponse(result, spinner)
}
const data = result.data
// Conclude the status of the API call
/** @typedef {(typeof data)[number]["value"] extends infer U | undefined ? U : never} SocketSdkIssue */
/** @type {Record<SocketSdkIssue["severity"], number>} */
const severityCount = { low: 0, middle: 0, high: 0, critical: 0 }
for (const issue of data) {
const value = issue.value
const issueSummary = getSeveritySummary(result.data)
spinner.succeed(`Found ${issueSummary || 'no'} issues for version ${pkgVersion} of ${pkgName}`)
if (!value) {
continue
}
return result
}
if (severityCount[value.severity] !== undefined) {
severityCount[value.severity] += 1
}
}
/**
* @param {import('@socketsecurity/sdk').SocketSdkReturnType<'getIssuesByNPMPackage'>["data"]} data
* @param {{ name: string, outputJson: boolean, outputMarkdown: boolean, pkgName: string, pkgVersion: string }} context
* @returns {void}
*/
function formatPackageDataOutput (data, { name, outputJson, outputMarkdown, pkgName, pkgVersion }) {
// If JSON, output and return...
const issueSummary = stringJoinWithSeparateFinalSeparator([
severityCount.critical ? severityCount.critical + ' critical' : undefined,
severityCount.high ? severityCount.high + ' high' : undefined,
severityCount.middle ? severityCount.middle + ' middle' : undefined,
severityCount.low ? severityCount.low + ' low' : undefined,
])
spinner.succeed(`Found ${issueSummary || 'no'} issues for version ${pkgVersion} of ${pkgName}`)
if (outputJson) {

@@ -144,2 +146,4 @@ console.log(JSON.stringify(data, undefined, 2))

// ...else do the CLI / Markdown output dance
const format = new ChalkOrMarkdown(!!outputMarkdown)

@@ -149,3 +153,2 @@ const url = `https://socket.dev/npm/package/${pkgName}/overview/${pkgVersion}`

console.log('\nDetailed info on socket.dev: ' + format.hyperlink(`${pkgName} v${pkgVersion}`, url, { fallbackToUrl: true }))
if (!outputMarkdown) {

@@ -155,4 +158,1 @@ console.log(chalk.dim('\nOr rerun', chalk.italic(name), 'using the', chalk.italic('--json'), 'flag to get full JSON output'))

}
/** @type {import('../../utils/meow-with-subcommands').CliSubcommand} */
export const info = { description, run }

@@ -6,3 +6,2 @@ /* eslint-disable no-console */

import chalk from 'chalk'
import meow from 'meow'

@@ -12,4 +11,5 @@ import ora from 'ora'

import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
import { ChalkOrMarkdown, logSymbols } from '../../utils/chalk-markdown.js'
import { AuthError, InputError } from '../../utils/errors.js'
import { InputError } from '../../utils/errors.js'
import { printFlagList } from '../../utils/formatting.js'

@@ -19,9 +19,49 @@ import { createDebugLogger } from '../../utils/misc.js'

import { isErrnoException } from '../../utils/type-helpers.js'
import { fetchReportData, formatReportDataOutput } from './view.js'
const description = 'Create a project report'
/** @type {import('../../utils/meow-with-subcommands').CliSubcommand} */
export const create = {
description: 'Create a project report',
async run (argv, importMeta, { parentName }) {
const name = parentName + ' create'
/** @type {import('../../utils/meow-with-subcommands').CliSubcommandRun} */
const run = async (argv, importMeta, { parentName }) => {
const name = parentName + ' create'
const input = await setupCommand(name, create.description, argv, importMeta)
if (input) {
const {
cwd,
debugLog,
dryRun,
outputJson,
outputMarkdown,
packagePaths,
view,
} = input
const result = input && await createReport(packagePaths, { cwd, debugLog, dryRun })
if (result && view) {
const reportId = result.data.id
const reportResult = input && await fetchReportData(reportId)
if (reportResult) {
formatReportDataOutput(reportResult.data, { name, outputJson, outputMarkdown, reportId })
}
} else if (result) {
formatReportCreationOutput(result.data, { outputJson, outputMarkdown })
}
}
}
}
// Internal functions
/**
* @param {string} name
* @param {string} description
* @param {readonly string[]} argv
* @param {ImportMeta} importMeta
* @returns {Promise<void|{ cwd: string, debugLog: typeof console.error, dryRun: boolean, outputJson: boolean, outputMarkdown: boolean, packagePaths: string[], view: boolean }>}
*/
async function setupCommand (name, description, argv, importMeta) {
const cli = meow(`

@@ -37,2 +77,3 @@ Usage

'--markdown': 'Output result as markdown',
'--view': 'Will wait for and return the created report'
}, 6)}

@@ -44,2 +85,3 @@

$ ${name} /path/to/a/package.json /path/to/another/package.json
$ ${name} . --view --json
`, {

@@ -69,2 +111,7 @@ argv,

},
view: {
type: 'boolean',
alias: 'v',
default: false,
},
}

@@ -77,2 +124,3 @@ })

markdown: outputMarkdown,
view,
} = cli.flags

@@ -90,2 +138,19 @@

return {
cwd,
debugLog,
dryRun,
outputJson,
outputMarkdown,
packagePaths,
view,
}
}
/**
* @param {string[]} packagePaths
* @param {{ cwd: string, debugLog: typeof console.error, dryRun: boolean }} context
* @returns {Promise<void|import('@socketsecurity/sdk').SocketSdkReturnType<'createReport'>>}
*/
async function createReport (packagePaths, { cwd, debugLog, dryRun }) {
debugLog(`${logSymbols.info} Uploading:`, packagePaths.join(`\n${logSymbols.info} Uploading:`))

@@ -98,28 +163,24 @@

const socketSdk = await setupSdk()
const spinner = ora(`Creating report with ${packagePaths.length} package files`).start()
const result = await handleApiCall(socketSdk.createReportFromFilePaths(packagePaths, cwd), spinner, 'creating report')
/** @type {Awaited<ReturnType<typeof socketSdk.createReportFromFilePaths>>} */
let result
try {
result = await socketSdk.createReportFromFilePaths(packagePaths, cwd)
} catch (cause) {
spinner.fail()
throw new ErrorWithCause('Failed creating report', { cause })
}
if (result.success === false) {
if (result.status === 401 || result.status === 403) {
spinner.stop()
throw new AuthError(result.error.message)
}
spinner.fail(chalk.white.bgRed('API returned an error:') + ' ' + result.error.message)
process.exit(1)
return handleUnsuccessfulApiResponse(result, spinner)
}
// Conclude the status of the API call
spinner.succeed()
return result
}
/**
* @param {import('@socketsecurity/sdk').SocketSdkReturnType<'createReport'>["data"]} data
* @param {{ outputJson: boolean, outputMarkdown: boolean }} context
* @returns {void}
*/
function formatReportCreationOutput (data, { outputJson, outputMarkdown }) {
if (outputJson) {
console.log(JSON.stringify(result.data, undefined, 2))
console.log(JSON.stringify(data, undefined, 2))
return

@@ -130,8 +191,5 @@ }

console.log('\nNew report: ' + format.hyperlink(result.data.id, result.data.url, { fallbackToUrl: true }))
console.log('\nNew report: ' + format.hyperlink(data.id, data.url, { fallbackToUrl: true }))
}
/** @type {import('../../utils/meow-with-subcommands').CliSubcommand} */
export const create = { description, run }
// TODO: Add globbing support with support for ignoring, as a "./**/package.json" in a project also traverses eg. node_modules

@@ -138,0 +196,0 @@ /**

import { meowWithSubcommands } from '../../utils/meow-with-subcommands.js'
import { create } from './create.js'
import { view } from './view.js'

@@ -13,2 +14,3 @@ const description = 'Project report related commands'

create,
view,
},

@@ -15,0 +17,0 @@ {

{
"name": "@socketsecurity/cli",
"version": "0.1.2",
"version": "0.2.0",
"description": "CLI tool for Socket.dev",

@@ -48,26 +48,26 @@ "homepage": "http://github.com/SocketDev/socket-cli-js",

"@types/prompts": "^2.4.1",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.44.0",
"c8": "^7.12.0",
"chai": "^4.3.6",
"dependency-check": "^5.0.0-7",
"eslint": "^8.23.0",
"eslint": "^8.28.0",
"eslint-config-standard": "^17.0.0",
"eslint-config-standard-jsx": "^11.0.0",
"eslint-import-resolver-typescript": "^3.5.1",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^39.5.0",
"eslint-plugin-n": "^15.3.0",
"eslint-plugin-promise": "^6.0.1",
"eslint-plugin-react": "^7.31.9",
"eslint-plugin-n": "^15.5.1",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.1",
"installed-check": "^6.0.4",
"installed-check": "^6.0.5",
"mocha": "^10.0.0",
"npm-run-all2": "^6.0.2",
"type-coverage": "^2.21.2",
"typescript": "~4.8.4"
"type-coverage": "^2.24.1",
"typescript": "~4.9.3"
},
"dependencies": {
"@socketsecurity/sdk": "^0.3.1",
"@socketsecurity/sdk": "^0.4.0",
"chalk": "^5.1.2",

@@ -79,3 +79,3 @@ "hpagent": "^1.2.0",

"ora": "^6.1.2",
"pony-cause": "^2.1.4",
"pony-cause": "^2.1.8",
"prompts": "^2.4.2",

@@ -82,0 +82,0 @@ "terminal-link": "^3.0.0"

@@ -18,3 +18,4 @@ # Socket CLI

socket info webtorrent@1.9.1
socket report create package.json
socket report create package.json --view
socket report view QXU8PmK7LfH608RAwfIKdbcHgwEd_ZeWJ9QEGv05FJUQ
```

@@ -25,9 +26,10 @@

* `socket info <package@version>` - looks up issues for a package
* `socket report create` - uploads the specified `package.json` and/or `package-lock.json` to create a report on [socket.dev](https://socket.dev/). If only one of a `package.json`/`package-lock.json` has been specified, the other will be automatically found and uploaded if it exists
* `socket report create <path(s)-to-folder-or-file>` - uploads the specified `package.json` and/or `package-lock.json` to create a report on [socket.dev](https://socket.dev/). If only one of a `package.json`/`package-lock.json` has been specified, the other will be automatically found and uploaded if it exists
* `socket report view <report-id>` - looks up issues and scores from a report
## Flags
### Action flags
### Command specific flags
* `--dry-run` - the `socket report create` supports running the command without actually uploading anything. All CLI tools that perform an action should have a dry run flag
* `--view` - when set on `socket report create` the command will immediately do a `socket report view` style view of the created report, waiting for the server to complete it

@@ -41,2 +43,3 @@ ### Output flags

* `--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
* `--debug` - outputs additional debug output. Great for debugging, geeks and us who develop. Hopefully you will never _need_ it, but it can still be fun, right?

@@ -51,2 +54,3 @@ * `--help` - prints the help for the current command. All CLI tools should have this flag

## Contributing
### Environment variables for development

@@ -57,6 +61,10 @@

## Similar projects
* [`@socketsecurity/sdk`](https://github.com/SocketDev/socket-sdk-js) - the SDK used in this CLI
## See also
* [`@socketsecurity/sdk`]('https://github.com/SocketDev/socket-sdk-js") - the SDK used in this CLI
* [Announcement blog post](https://socket.dev/blog/announcing-socket-cli-preview)
* [Socket API Reference](https://docs.socket.dev/reference) - the API used in this CLI
* [Socket GitHub App](https://github.com/apps/socket-security) - the plug-and-play GitHub App
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc