Skip to content

Change handle API to be --json safe #509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 3 additions & 28 deletions src/commands/analytics/fetch-org-analytics.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import constants from '../../constants.mts'
import { handleApiCall, handleFailedApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'
Expand All @@ -10,32 +9,8 @@ export async function fetchOrgAnalyticsData(
): Promise<CResult<SocketSdkReturnType<'getOrgAnalytics'>['data']>> {
const sockSdk = await setupSdk()

// Lazily access constants.spinner.
const { spinner } = constants

spinner.start(`Requesting analytics data from API...`)

const result = await handleApiCall(
return await handleApiCall(
sockSdk.getOrgAnalytics(time.toString()),
'fetching analytics data'
'analytics data'
)

spinner.successAndStop(`Received API response.`)

if (result.success === false) {
return handleFailedApiResponse('getOrgAnalytics', result)
}

if (!result.data.length) {
return {
ok: true,
message: 'No analytics data is available for this organization yet.',
data: []
}
}

return {
ok: true,
data: result.data
}
}
31 changes: 3 additions & 28 deletions src/commands/analytics/fetch-repo-analytics.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import constants from '../../constants.mts'
import { handleApiCall, handleFailedApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'
Expand All @@ -11,32 +10,8 @@ export async function fetchRepoAnalyticsData(
): Promise<CResult<SocketSdkReturnType<'getRepoAnalytics'>['data']>> {
const sockSdk = await setupSdk()

// Lazily access constants.spinner.
const { spinner } = constants

spinner.start(`Requesting analytics data from API...`)

const result = await handleApiCall(
return await handleApiCall(
sockSdk.getRepoAnalytics(repo, time.toString()),
'fetching analytics data'
'analytics data'
)

spinner.successAndStop(`Received API response.`)

if (result.success === false) {
return handleFailedApiResponse('getRepoAnalytics', result)
}

if (!result.data.length) {
return {
ok: true,
message: 'No analytics data is available for this repository yet.',
data: []
}
}

return {
ok: true,
data: result.data
}
}
7 changes: 7 additions & 0 deletions src/commands/analytics/handle-analytics.mts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ export async function handleAnalytics({
message: 'Missing repository name in command'
}
}
if (result.ok && !result.data.length) {
result = {
ok: true,
message: `The analytics data for this ${scope === 'org' ? 'organization' : 'repository'} is not yet available.`,
data: []
}
}

await outputAnalytics(result, {
filePath,
Expand Down
23 changes: 3 additions & 20 deletions src/commands/audit-log/fetch-audit-log.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import constants from '../../constants.mts'
import { handleApiCall, handleFailedApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult, OutputKind } from '../../types.mts'
Expand All @@ -20,12 +19,7 @@ export async function fetchAuditLog({
}): Promise<CResult<SocketSdkReturnType<'getAuditLogEvents'>['data']>> {
const sockSdk = await setupSdk()

// Lazily access constants.spinner.
const { spinner } = constants

spinner.start(`Looking up audit log for ${orgSlug}`)

const result = await handleApiCall(
return await handleApiCall(
sockSdk.getAuditLogEvents(orgSlug, {
// I'm not sure this is used at all.
outputJson: String(outputKind === 'json'),
Expand All @@ -36,17 +30,6 @@ export async function fetchAuditLog({
page: String(page),
per_page: String(perPage)
}),
`Looking up audit log for ${orgSlug}\n`
`audit log for ${orgSlug}`
)

spinner.successAndStop(`Received API response.`)

if (!result.success) {
return handleFailedApiResponse('getAuditLogEvents', result)
}

return {
ok: true,
data: result.data
}
}
23 changes: 8 additions & 15 deletions src/commands/ci/fetch-default-org-slug.mts
Original file line number Diff line number Diff line change
@@ -1,36 +1,29 @@
import { debugLog } from '@socketsecurity/registry/lib/debug'

import { handleApiCall } from '../../utils/api.mts'
import { getConfigValue } from '../../utils/config.mts'
import { getConfigValueOrUndef } from '../../utils/config.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'

// Use the config defaultOrg when set, otherwise discover from remote
export async function getDefaultOrgSlug(): Promise<CResult<string>> {
const defaultOrgResult = getConfigValue('defaultOrg')
if (!defaultOrgResult.ok) {
return defaultOrgResult
}
const defaultOrgResult = getConfigValueOrUndef('defaultOrg')

if (defaultOrgResult.data) {
debugLog(`Using default org: ${defaultOrgResult.data}`)
return { ok: true, data: defaultOrgResult.data }
if (defaultOrgResult) {
debugLog(`Using default org: ${defaultOrgResult}`)
return { ok: true, data: defaultOrgResult }
}

const sockSdk = await setupSdk()

const result = await handleApiCall(
sockSdk.getOrganizations(),
'looking up organizations'
'list of organizations'
)

if (!result.success) {
return {
ok: false,
message: result.error,
data: `Failed to fetch default organization from API. Unable to continue.${result.cause ? ` ( Reason given: ${result.cause} )` : ''}`
}
if (!result.ok) {
return result
}

const orgs = result.data.organizations
Expand Down
8 changes: 4 additions & 4 deletions src/commands/config/discover-config-value.mts
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ async function getDefaultOrgFromToken(): Promise<

const result = await handleApiCall(
sockSdk.getOrganizations(),
'looking up organizations'
'list of organizations'
)

if (result.success) {
if (result.ok) {
const arr = Array.from(Object.values(result.data.organizations)).map(
({ slug }) => slug
)
Expand All @@ -157,10 +157,10 @@ async function getEnforceableOrgsFromToken(): Promise<string[] | undefined> {

const result = await handleApiCall(
sockSdk.getOrganizations(),
'looking up organizations'
'list of organizations'
)

if (result.success) {
if (result.ok) {
const arr = Array.from(Object.values(result.data.organizations)).map(
({ slug }) => slug
)
Expand Down
20 changes: 3 additions & 17 deletions src/commands/dependencies/fetch-dependencies.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import constants from '../../constants.mts'
import { handleApiCall, handleFailedApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'
Expand All @@ -14,21 +13,8 @@ export async function fetchDependencies({
}): Promise<CResult<SocketSdkReturnType<'searchDependencies'>['data']>> {
const sockSdk = await setupSdk()

// Lazily access constants.spinner.
const { spinner } = constants

spinner.start('Fetching organization dependencies...')

const result = await handleApiCall(
return await handleApiCall(
sockSdk.searchDependencies({ limit, offset }),
'Searching dependencies'
'organization dependencies'
)

spinner.successAndStop('Received organization dependencies response.')

if (!result.success) {
return handleFailedApiResponse('searchDependencies', result)
}

return { ok: true, data: result.data }
}
10 changes: 3 additions & 7 deletions src/commands/diff-scan/fetch-diff-scan.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import constants from '../../constants.mts'
import { handleApiCall, handleApiError, queryApi } from '../../utils/api.mts'
import { handleApiError, queryApi } from '../../utils/api.mts'
import { getDefaultToken } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'
Expand Down Expand Up @@ -37,12 +37,8 @@ export async function fetchDiffScan({
}
}

const result = await handleApiCall(
(await response.json()) as Promise<
SocketSdkReturnType<'GetOrgDiffScan'>['data']
>,
'Deserializing json'
)
const result =
(await response.json()) as SocketSdkReturnType<'GetOrgDiffScan'>['data']

return { ok: true, data: result }
}
34 changes: 16 additions & 18 deletions src/commands/info/fetch-package-info.mts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import constants from '../../constants.mts'
import { getSeverityCount } from '../../utils/alert/severity.mts'
import {
handleApiCall,
Expand All @@ -15,32 +14,31 @@ export async function fetchPackageInfo(
): Promise<void | PackageData> {
const sockSdk = await setupSdk(getPublicToken())

// 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 result = await handleApiCall(
sockSdk.getIssuesByNPMPackage(pkgName, pkgVersion),
'looking up package'
'package issues'
)
const scoreResult = await handleApiCall(
sockSdk.getScoreByNPMPackage(pkgName, pkgVersion),
'looking up package score'
'package score'
)

spinner.successAndStop('Data fetched')

if (result.success === false) {
handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result)
if (!result.ok) {
handleUnsuccessfulApiResponse(
'getIssuesByNPMPackage',
result.message,
result.cause ?? '',
(result.data as any)?.code ?? 0
)
}

if (scoreResult.success === false) {
handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult)
if (!scoreResult.ok) {
handleUnsuccessfulApiResponse(
'getScoreByNPMPackage',
scoreResult.message,
scoreResult.cause ?? '',
(scoreResult.data as any)?.code ?? 0
)
}

const severityCount = getSeverityCount(
Expand Down
22 changes: 9 additions & 13 deletions src/commands/login/attempt-login.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import { confirm, password, select } from '@socketsecurity/registry/lib/prompts'

import { applyLogin } from './apply-login.mts'
import constants from '../../constants.mts'
import { handleUnsuccessfulApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { getConfigValueOrUndef, isReadOnlyConfig } from '../../utils/config.mts'
import { failMsgWithBadge } from '../../utils/fail-msg-with-badge.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { Choice, Separator } from '@socketsecurity/registry/lib/prompts'
Expand All @@ -29,20 +30,17 @@ export async function attemptLogin(
'https://docs.socket.dev/docs/api-keys'
)} (leave blank for a public key)`
})) || SOCKET_PUBLIC_API_TOKEN
// Lazily access constants.spinner.
const { spinner } = constants

const sdk = await setupSdk(apiToken, apiBaseUrl, apiProxy)

spinner.start('Verifying API key...')
const result = await handleApiCall(
sdk.getOrganizations(),
'token verification'
)

const result = await sdk.getOrganizations()

spinner.successAndStop('Received response')

if (!result.success) {
logger.fail('Authentication failed...')
handleUnsuccessfulApiResponse('getOrganizations', result)
if (!result.ok) {
logger.fail(failMsgWithBadge(result.message, result.cause))
return
}

logger.success('API key verified')
Expand Down Expand Up @@ -84,8 +82,6 @@ export async function attemptLogin(
}
}

spinner.stop()

const previousPersistedToken = getConfigValueOrUndef('apiToken')
try {
applyLogin(apiToken, enforcedOrgs, apiBaseUrl, apiProxy)
Expand Down
20 changes: 3 additions & 17 deletions src/commands/organization/fetch-license-policy.mts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import constants from '../../constants.mts'
import { handleApiCall, handleFailedApiResponse } from '../../utils/api.mts'
import { handleApiCall } from '../../utils/api.mts'
import { setupSdk } from '../../utils/sdk.mts'

import type { CResult } from '../../types.mts'
Expand All @@ -10,21 +9,8 @@ export async function fetchLicensePolicy(
): Promise<CResult<SocketSdkReturnType<'getOrgLicensePolicy'>['data']>> {
const sockSdk = await setupSdk()

// Lazily access constants.spinner.
const { spinner } = constants

spinner.start('Fetching organization license policy...')

const result = await handleApiCall(
return await handleApiCall(
sockSdk.getOrgLicensePolicy(orgSlug),
'looking up organization quota'
'organization license policy'
)

spinner.successAndStop('Received organization license policy response.')

if (!result.success) {
return handleFailedApiResponse('getOrgLicensePolicy', result)
}

return { ok: true, data: result.data }
}
Loading
Loading