Skip to content

Commit 17fd85b

Browse files
pvdzjdalton
andcommitted
[socket config] Add configuration commands (#381)
--------- Signed-off-by: John-David Dalton <[email protected]> Co-authored-by: John-David Dalton <[email protected]>
1 parent 6d7a6a1 commit 17fd85b

26 files changed

+1065
-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: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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+
Keys:
30+
31+
- apiBaseUrl -- Base URL of the API endpoint
32+
- apiToken -- The API token required to access most API endpoints
33+
- apiProxy -- A proxy through which to access the API
34+
- enforcedOrgs -- Orgs in this list have their security policies enforced on this machine
35+
36+
Examples
37+
$ socket config get FakeOrg --repoName=test-repo"
38+
`
39+
)
40+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
41+
"
42+
_____ _ _ /---------------
43+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
44+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
45+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
46+
`)
47+
48+
expect(code, 'help should exit with code 2').toBe(2)
49+
expect(stderr, 'header should include command (without params)').toContain(
50+
'`socket config get`'
51+
)
52+
})
53+
54+
cmdit(
55+
['config', 'get', '--dry-run'],
56+
'should require args with just dry-run',
57+
async cmd => {
58+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
59+
expect(stdout).toMatchInlineSnapshot(`""`)
60+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
61+
"
62+
_____ _ _ /---------------
63+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
64+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
65+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>
66+
67+
\\x1b[31m\\xd7\\x1b[39m \\x1b[41m\\x1b[37mInput error\\x1b[39m\\x1b[49m: Please provide the required fields:
68+
69+
- Config key should be the first arg \\x1b[31m(missing!)\\x1b[39m"
70+
`)
71+
72+
expect(code, 'dry-run should exit with code 2 if missing input').toBe(2)
73+
}
74+
)
75+
76+
cmdit(
77+
['config', 'get', 'test', '--dry-run'],
78+
'should require args with just dry-run',
79+
async cmd => {
80+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
81+
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
82+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
83+
"
84+
_____ _ _ /---------------
85+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
86+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
87+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
88+
`)
89+
90+
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
91+
}
92+
)
93+
})

src/commands/config/cmd-config-get.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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 { supportedConfigKeys } from '../../utils/config'
10+
import { meowOrExit } from '../../utils/meow-with-subcommands'
11+
import { getFlagListOutput } from '../../utils/output-formatting'
12+
13+
import type { LocalConfig } from '../../utils/config'
14+
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
15+
16+
const { DRY_RUN_BAIL_TEXT } = constants
17+
18+
const config: CliCommandConfig = {
19+
commandName: 'get',
20+
description: 'Get the value of a local CLI config item',
21+
hidden: false,
22+
flags: {
23+
...commonFlags,
24+
...outputFlags
25+
},
26+
help: (command, config) => `
27+
Usage
28+
$ ${command} <org slug>
29+
30+
Options
31+
${getFlagListOutput(config.flags, 6)}
32+
33+
Keys:
34+
35+
${Array.from(supportedConfigKeys.entries())
36+
.map(([key, desc]) => ` - ${key} -- ${desc}`)
37+
.join('\n')}
38+
39+
Examples
40+
$ ${command} FakeOrg --repoName=test-repo
41+
`
42+
}
43+
44+
export const cmdConfigGet = {
45+
description: config.description,
46+
hidden: config.hidden,
47+
run
48+
}
49+
50+
async function run(
51+
argv: string[] | readonly string[],
52+
importMeta: ImportMeta,
53+
{ parentName }: { parentName: string }
54+
): Promise<void> {
55+
const cli = meowOrExit({
56+
argv,
57+
config,
58+
importMeta,
59+
parentName
60+
})
61+
62+
const { json, markdown } = cli.flags
63+
const [key = ''] = cli.input
64+
65+
if (!supportedConfigKeys.has(key as keyof LocalConfig) && key !== 'test') {
66+
// Use exit status of 2 to indicate incorrect usage, generally invalid
67+
// options or missing arguments.
68+
// https://www.gnu.org/software/bash/manual/html_node/Exit-Status.html
69+
process.exitCode = 2
70+
logger.fail(stripIndents`${colors.bgRed(colors.white('Input error'))}: Please provide the required fields:
71+
72+
- Config key should be the first arg ${!key ? colors.red('(missing!)') : !supportedConfigKeys.has(key as any) ? colors.red('(invalid config key!)') : colors.green('(ok)')}
73+
`)
74+
return
75+
}
76+
77+
if (cli.flags['dryRun']) {
78+
logger.log(DRY_RUN_BAIL_TEXT)
79+
return
80+
}
81+
82+
await handleConfigGet({
83+
key: key as keyof LocalConfig,
84+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
85+
})
86+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
Keys:
31+
32+
- apiBaseUrl -- Base URL of the API endpoint
33+
- apiToken -- The API token required to access most API endpoints
34+
- apiProxy -- A proxy through which to access the API
35+
- enforcedOrgs -- Orgs in this list have their security policies enforced on this machine
36+
37+
Examples
38+
$ socket config list FakeOrg --repoName=test-repo"
39+
`
40+
)
41+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
42+
"
43+
_____ _ _ /---------------
44+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
45+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
46+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config list\`, cwd: <redacted>"
47+
`)
48+
49+
expect(code, 'help should exit with code 2').toBe(2)
50+
expect(stderr, 'header should include command (without params)').toContain(
51+
'`socket config list`'
52+
)
53+
})
54+
55+
cmdit(
56+
['config', 'list', '--dry-run'],
57+
'should require args with just dry-run',
58+
async cmd => {
59+
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd)
60+
expect(stdout).toMatchInlineSnapshot(`"[DryRun]: Bailing now"`)
61+
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
62+
"
63+
_____ _ _ /---------------
64+
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
65+
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
66+
|_____|___|___|_,_|___|_|.dev | Command: \`socket config list\`, cwd: <redacted>"
67+
`)
68+
69+
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
70+
}
71+
)
72+
})
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 { supportedConfigKeys } from '../../utils/config'
7+
import { meowOrExit } from '../../utils/meow-with-subcommands'
8+
import { getFlagListOutput } from '../../utils/output-formatting'
9+
10+
import type { CliCommandConfig } from '../../utils/meow-with-subcommands'
11+
12+
const { DRY_RUN_BAIL_TEXT } = constants
13+
14+
const config: CliCommandConfig = {
15+
commandName: 'list',
16+
description: 'Show all local CLI config items and their values',
17+
hidden: false,
18+
flags: {
19+
...commonFlags,
20+
...outputFlags,
21+
full: {
22+
type: 'boolean',
23+
default: false,
24+
description: 'Show full tokens in plaintext (unsafe)'
25+
}
26+
},
27+
help: (command, config) => `
28+
Usage
29+
$ ${command} <org slug>
30+
31+
Options
32+
${getFlagListOutput(config.flags, 6)}
33+
34+
Keys:
35+
36+
${Array.from(supportedConfigKeys.entries())
37+
.map(([key, desc]) => ` - ${key} -- ${desc}`)
38+
.join('\n')}
39+
40+
Examples
41+
$ ${command} FakeOrg --repoName=test-repo
42+
`
43+
}
44+
45+
export const cmdConfigList = {
46+
description: config.description,
47+
hidden: config.hidden,
48+
run
49+
}
50+
51+
async function run(
52+
argv: string[] | readonly string[],
53+
importMeta: ImportMeta,
54+
{ parentName }: { parentName: string }
55+
): Promise<void> {
56+
const cli = meowOrExit({
57+
argv,
58+
config,
59+
importMeta,
60+
parentName
61+
})
62+
63+
const { full, json, markdown } = cli.flags
64+
65+
if (cli.flags['dryRun']) {
66+
logger.log(DRY_RUN_BAIL_TEXT)
67+
return
68+
}
69+
70+
await outputConfigList({
71+
full: !!full,
72+
outputKind: json ? 'json' : markdown ? 'markdown' : 'text'
73+
})
74+
}

0 commit comments

Comments
 (0)