Skip to content

Commit 5e52e1f

Browse files
committed
[socket config] Add configuration commands
1 parent 3dec148 commit 5e52e1f

26 files changed

+1022
-74
lines changed

src/cli.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'
1212
import { cmdAnalytics } from './commands/analytics/cmd-analytics'
1313
import { cmdAuditLog } from './commands/audit-log/cmd-audit-log'
1414
import { cmdCdxgen } from './commands/cdxgen/cmd-cdxgen'
15+
import { cmdConfig } from './commands/config/cmd-config'
1516
import { cmdScanCreate } from './commands/dependencies/cmd-dependencies'
1617
import { cmdDiffScan } from './commands/diff-scan/cmd-diff-scan'
1718
import { cmdFix } from './commands/fix/cmd-fix'
@@ -51,6 +52,7 @@ void (async () => {
5152
await meowWithSubcommands(
5253
{
5354
cdxgen: cmdCdxgen,
55+
config: cmdConfig,
5456
fix: cmdFix,
5557
info: cmdInfo,
5658
login: cmdLogin,
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import path from 'node:path'
2+
3+
import { describe, expect } from 'vitest'
4+
5+
import constants from '../../../dist/constants.js'
6+
import { cmdit, invokeNpm } from '../../../test/utils'
7+
8+
const { CLI } = constants
9+
10+
describe('socket config get', async () => {
11+
// Lazily access constants.rootBinPath.
12+
const entryPath = path.join(constants.rootBinPath, `${CLI}.js`)
13+
14+
cmdit(['config', 'get', '--help'], 'should support --help', async cmd => {
15+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
16+
expect(stdout).toMatchInlineSnapshot(
17+
`
18+
"Get the value of a local CLI config item
19+
20+
Usage
21+
$ socket config get <org slug>
22+
23+
Options
24+
--dryRun Do input validation for a command and exit 0 when input is ok
25+
--help Print this help.
26+
--json Output result as json
27+
--markdown Output result as markdown
28+
29+
Examples
30+
$ socket config get FakeOrg --repoName=test-repo"
31+
`
32+
)
33+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
34+
"
35+
_____ _ _ /---------------
36+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
37+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
38+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
39+
`)
40+
41+
expect(code, 'help should exit with code 2').toBe(2)
42+
expect(stderr, 'header should include command (without params)').toContain(
43+
'`socket config get`'
44+
)
45+
})
46+
47+
cmdit(
48+
['config', 'get', '--dry-run'],
49+
'should require args with just dry-run',
50+
async cmd => {
51+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
52+
expect(stdout).toMatchInlineSnapshot(`""`)
53+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
54+
"
55+
_____ _ _ /---------------
56+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
57+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
58+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>
59+
60+
\\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[37mInput error\\x1b[39m\\x1b[49m: Please provide the required fields:
61+
62+
- Config key should be the first arg \\x1b[31m(missing!)\\x1b[39m"
63+
`)
64+
65+
expect(code, 'dry-run should exit with code 2 if missing input').toBe(2)
66+
}
67+
)
68+
69+
cmdit(
70+
['config', 'get', 'test', '--dry-run'],
71+
'should require args with just dry-run',
72+
async cmd => {
73+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
74+
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
75+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
76+
"
77+
_____ _ _ /---------------
78+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
79+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
80+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
81+
`)
82+
83+
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
84+
}
85+
)
86+
})
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { stripIndents } from 'common-tags'
2+
import colors from 'yoctocolors-cjs'
3+
4+
import { logger } from '@socketsecurity/registry/lib/logger'
5+
6+
import { handleConfigGet } from './handle-config-get'
7+
import constants from '../../constants'
8+
import { commonFlags, outputFlags } from '../../flags'
9+
import { LocalConfig, supportedConfigKeys } from '../../utils/config'
10+
import { meowOrExit } from '../../utils/meow-with-subcommands'
11+
import { getFlagListOutput } from '../../utils/output-formatting'
12+
13+
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
14+
15+
const { DRY_RUN_BAIL_TEXT } = constants
16+
17+
const config: CliCommandConfig = {
18+
commandName: 'get',
19+
description: 'Get the value of a local CLI config item',
20+
hidden: false,
21+
flags: {
22+
...commonFlags,
23+
...outputFlags
24+
},
25+
help: (command, config) => `
26+
Usage
27+
$ ${command} <org slug>
28+
29+
Options
30+
${getFlagListOutput(config.flags, 6)}
31+
32+
Examples
33+
$ ${command} FakeOrg --repoName=test-repo
34+
`
35+
}
36+
37+
export const cmdConfigGet = {
38+
description: config.description,
39+
hidden: config.hidden,
40+
run
41+
}
42+
43+
async function run(
44+
argv: string[] | readonly string[],
45+
importMeta: ImportMeta,
46+
{ parentName }: { parentName: string }
47+
): Promise<void> {
48+
const cli = meowOrExit({
49+
argv,
50+
config,
51+
importMeta,
52+
parentName
53+
})
54+
55+
const { json, markdown } = cli.flags
56+
const [key = ''] = cli.input
57+
58+
if (!supportedConfigKeys.has(key as keyof LocalConfig) && key !== 'test') {
59+
// Use exit status of 2 to indicate incorrect usage, generally invalid
60+
// options or missing arguments.
61+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
62+
process.exitCode = 2
63+
logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
64+
65+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !supportedConfigKeys.has(key as any) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
66+
`)
67+
return
68+
}
69+
70+
if (cli.flags['dryRun']) {
71+
logger.log(DRY_RUN_BAIL_TEXT)
72+
return
73+
}
74+
75+
await handleConfigGet({
76+
key: key as keyof LocalConfig,
77+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
78+
})
79+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import path from 'node:path'
2+
3+
import { describe, expect } from 'vitest'
4+
5+
import constants from '../../../dist/constants.js'
6+
import { cmdit, invokeNpm } from '../../../test/utils'
7+
8+
const { CLI } = constants
9+
10+
describe('socket config get', async () => {
11+
// Lazily access constants.rootBinPath.
12+
const entryPath = path.join(constants.rootBinPath, `${CLI}.js`)
13+
14+
cmdit(['config', 'list', '--help'], 'should support --help', async cmd => {
15+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
16+
expect(stdout).toMatchInlineSnapshot(
17+
`
18+
"Show all local CLI config items and their values
19+
20+
Usage
21+
$ socket config list <org slug>
22+
23+
Options
24+
--dryRun Do input validation for a command and exit 0 when input is ok
25+
--full Show full tokens in plaintext (unsafe)
26+
--help Print this help.
27+
--json Output result as json
28+
--markdown Output result as markdown
29+
30+
Examples
31+
$ socket config list FakeOrg --repoName=test-repo"
32+
`
33+
)
34+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
35+
"
36+
_____ _ _ /---------------
37+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
38+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
39+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config list\`, cwd: <redacted>"
40+
`)
41+
42+
expect(code, 'help should exit with code 2').toBe(2)
43+
expect(stderr, 'header should include command (without params)').toContain(
44+
'`socket config list`'
45+
)
46+
})
47+
48+
cmdit(
49+
['config', 'list', '--dry-run'],
50+
'should require args with just dry-run',
51+
async cmd => {
52+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
53+
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
54+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
55+
"
56+
_____ _ _ /---------------
57+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
58+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
59+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config list\`, cwd: <redacted>"
60+
`)
61+
62+
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
63+
}
64+
)
65+
})
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { logger } from '@socketsecurity/registry/lib/logger'
2+
3+
import { outputConfigList } from './output-config-list'
4+
import constants from '../../constants'
5+
import { commonFlags, outputFlags } from '../../flags'
6+
import { meowOrExit } from '../../utils/meow-with-subcommands'
7+
import { getFlagListOutput } from '../../utils/output-formatting'
8+
9+
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
10+
11+
const { DRY_RUN_BAIL_TEXT } = constants
12+
13+
const config: CliCommandConfig = {
14+
commandName: 'list',
15+
description: 'Show all local CLI config items and their values',
16+
hidden: false,
17+
flags: {
18+
...commonFlags,
19+
...outputFlags,
20+
full: {
21+
type: 'boolean',
22+
default: false,
23+
description: 'Show full tokens in plaintext (unsafe)'
24+
}
25+
},
26+
help: (command, config) => `
27+
Usage
28+
$ ${command} <org slug>
29+
30+
Options
31+
${getFlagListOutput(config.flags, 6)}
32+
33+
Examples
34+
$ ${command} FakeOrg --repoName=test-repo
35+
`
36+
}
37+
38+
export const cmdConfigList = {
39+
description: config.description,
40+
hidden: config.hidden,
41+
run
42+
}
43+
44+
async function run(
45+
argv: string[] | readonly string[],
46+
importMeta: ImportMeta,
47+
{ parentName }: { parentName: string }
48+
): Promise<void> {
49+
const cli = meowOrExit({
50+
argv,
51+
config,
52+
importMeta,
53+
parentName
54+
})
55+
56+
const { full, json, markdown } = cli.flags
57+
58+
if (cli.flags['dryRun']) {
59+
logger.log(DRY_RUN_BAIL_TEXT)
60+
return
61+
}
62+
63+
await outputConfigList({
64+
full: !!full,
65+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
66+
})
67+
}

0 commit comments

Comments
 (0)