Skip to content
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
4 changes: 2 additions & 2 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { cmdNpm } from './commands/npm/cmd-npm'
import { cmdNpx } from './commands/npx/cmd-npx'
import { cmdOops } from './commands/oops/cmd-oops'
import { cmdOptimize } from './commands/optimize/cmd-optimize'
import { cmdOrganizations } from './commands/organizations/cmd-organizations'
import { cmdOrganization } from './commands/organization/cmd-organization'
import { cmdRawNpm } from './commands/raw-npm/cmd-raw-npm'
import { cmdRawNpx } from './commands/raw-npx/cmd-raw-npx'
import { cmdReport } from './commands/report/cmd-report'
Expand Down Expand Up @@ -58,7 +58,7 @@ void (async () => {
npx: cmdNpx,
oops: cmdOops,
optimize: cmdOptimize,
organization: cmdOrganizations,
organization: cmdOrganization,
'raw-npm': cmdRawNpm,
'raw-npx': cmdRawNpx,
report: cmdReport,
Expand Down
63 changes: 63 additions & 0 deletions src/commands/organization/cmd-organization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { getOrganization } from './get-organization.ts'
import { meowOrExit } from '../../utils/meow-with-subcommands'
import { getFlagListOutput } from '../../utils/output-formatting'

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

Check warning on line 5 in src/commands/organization/cmd-organization.ts

View workflow job for this annotation

GitHub Actions / Linting / Test (20, ubuntu-latest)

There should be at least one empty line between import groups
import { commonFlags, outputFlags } from '../../flags.ts'

Check warning on line 6 in src/commands/organization/cmd-organization.ts

View workflow job for this annotation

GitHub Actions / Linting / Test (20, ubuntu-latest)

There should be at least one empty line between import groups

Check warning on line 6 in src/commands/organization/cmd-organization.ts

View workflow job for this annotation

GitHub Actions / Linting / Test (20, ubuntu-latest)

`../../flags.ts` import should occur before import of `../../utils/meow-with-subcommands`
import colors from 'yoctocolors-cjs'

Check warning on line 7 in src/commands/organization/cmd-organization.ts

View workflow job for this annotation

GitHub Actions / Linting / Test (20, ubuntu-latest)

`yoctocolors-cjs` import should occur before import of `./get-organization.ts`

const config: CliCommandConfig = {
commandName: 'organizations',
description: 'List organizations associated with the API key used',
hidden: false,
flags: {
...commonFlags,
...outputFlags
},
help: (command, _config) => `
Usage
$ ${command}

Options
${getFlagListOutput(config.flags, 6)}
`
}

export const cmdOrganization = {
description: config.description,
hidden: config.hidden,
run
}

async function run(
argv: readonly string[],
importMeta: ImportMeta,
{ parentName }: { parentName: string }
): Promise<void> {
const cli = meowOrExit({
argv,
config,
importMeta,
parentName
})

const json = Boolean(cli.flags['json'])
const markdown = Boolean(cli.flags['markdown'])
if (json && markdown) {
// Use exit status of 2 to indicate incorrect usage, generally invalid
// options or missing arguments.
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
process.exitCode = 2
console.error(`
${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:\n
- The json and markdown flags cannot be both set, pick one
`)
return
}

if (cli.flags['dryRun']) {
return console.log('[DryRun] Bailing now')
}

await getOrganization(json ? 'json' : markdown ? 'markdown' : 'text')
}
98 changes: 98 additions & 0 deletions src/commands/organization/get-organization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import colors from 'yoctocolors-cjs'

import { Spinner } from '@socketsecurity/registry/lib/spinner'

import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api'
import { AuthError } from '../../utils/errors'
import { getDefaultToken, setupSdk } from '../../utils/sdk'

export async function getOrganization(
format: 'text' | 'json' | 'markdown' = 'text'
): Promise<void> {
const apiToken = getDefaultToken()
if (!apiToken) {
throw new AuthError(
'User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.'
)
}

await printOrganizationsFromToken(apiToken, format)
}

async function printOrganizationsFromToken(
apiToken: string,
format: 'text' | 'json' | 'markdown' = 'text'
) {
const spinner = new Spinner({ text: 'Fetching organizations...' }).start()
const socketSdk = await setupSdk(apiToken)
const result = await handleApiCall(
socketSdk.getOrganizations(),
'looking up organizations'
)

if (result.success === false) {
handleUnsuccessfulApiResponse('getOrganizations', result, spinner)
return
}

spinner.stop('')

const organizations = Object.values(result.data.organizations)

if (format === 'json') {
const obj = Array.from(organizations).map(o => ({
name: o.name,
id: o.id,
plan: o.plan
}))
console.log(JSON.stringify(obj, null, 2))
return
}

if (format === 'markdown') {
// | Syntax | Description |
// | ----------- | ----------- |
// | Header | Title |
// | Paragraph | Text |

let mw1 = 4
let mw2 = 2
let mw3 = 4
for (const o of organizations) {
mw1 = Math.max(mw1, (o?.name || '').length)
mw2 = Math.max(mw2, (o?.id || '').length)
mw3 = Math.max(mw3, (o?.plan || '').length)
}

console.log('# Organizations\n')
console.log(
`List of organizations associated with your API key, ending with: ${colors.italic(apiToken.slice(-10, -4))}\n`
)
console.log(
`| Name${' '.repeat(mw1 - 4)} | ID${' '.repeat(mw2 - 2)} | Plan${' '.repeat(mw3 - 4)} |`
)
console.log(
`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} | ${'-'.repeat(mw3)} |`
)
for (const o of organizations) {
console.log(
`| ${(o?.name || '').padEnd(mw1, ' ')} | ${(o?.id || '').padEnd(mw2, ' ')} | ${(o?.plan || '').padEnd(mw3, ' ')} |`
)
}
console.log(
`| ${'-'.repeat(mw1)} | ${'-'.repeat(mw2)} | ${'-'.repeat(mw3)} |`
)
return
}

console.log(
`List of organizations associated with your API key, ending with: ${colors.italic(apiToken.slice(-10, -4))}\n`
)

// Just dump
for (const o of organizations) {
console.log(
`- Name: ${colors.bold(o?.name)}, ID: ${colors.bold(o?.id)}, Plan: ${colors.bold(o?.plan)}`
)
}
}
40 changes: 0 additions & 40 deletions src/commands/organizations/cmd-organizations.ts

This file was deleted.

40 changes: 0 additions & 40 deletions src/commands/organizations/get-organizations.ts

This file was deleted.

1 change: 1 addition & 0 deletions src/utils/meow-with-subcommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export function meowOrExit({
if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
console.log(getAsciiHeader(command))
}

// This exits if .printHelp() is called either by meow itself or by us.
const cli = meow({
argv,
Expand Down
19 changes: 19 additions & 0 deletions test/dry-run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,25 @@ describe('dry-run on all commands', async () => {
)
})

cmdit(['organization', '--dry-run'], 'should support', async cmd => {
const { code, status, stderr, stdout } = await invoke(...cmd)
expect(`\n ${stdout}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket organizations\`, cwd: <redacted>

[DryRun] Bailing now"
`)
expect(stderr).toMatchInlineSnapshot(`""`)

expect(code, 'dry-run should exit with code 0 if input is ok').toBe(0)
expect(stdout, 'header should include command (without params)').toContain(
cmd.slice(0, cmd.indexOf('--dry-run')).join(' ')
)
})

cmdit(['raw-npm', '--dry-run'], 'should support', async cmd => {
const { code, status, stderr, stdout } = await invoke(...cmd)
expect(`\n ${stdout}`).toMatchInlineSnapshot(`
Expand Down
Loading