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
220 changes: 220 additions & 0 deletions src/commands/config/cmd-config-get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,224 @@ describe('socket config get', async () => {
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
}
)

describe('env vars', () => {
describe('token', () => {
cmdit(
['config', 'get', 'apiToken', '--config', '{"apiToken":null}'],
'should return undefined when token not set in config',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: null

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: null')).toBe(true)
}
)

cmdit(
['config', 'get', 'apiToken', '--config', '{"apiToken":null}'],
'should return the env var token when set',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {
SOCKET_SECURITY_API_TOKEN: 'abc'
})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: abc

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: abc')).toBe(true)
}
)

// Migrate this away...?
cmdit(
['config', 'get', 'apiToken', '--config', '{"apiToken":null}'],
'should backwards compat support api key as well env var',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {
SOCKET_SECURITY_API_KEY: 'abc'
})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: abc

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: abc')).toBe(true)
}
)

cmdit(
['config', 'get', 'apiToken', '--config', '{"apiToken":null}'],
'should be nice and support cli prefixed env var for token as well',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {
SOCKET_CLI_API_TOKEN: 'abc'
})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: abc

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: abc')).toBe(true)
}
)

// Migrate this away...?
cmdit(
['config', 'get', 'apiToken', '--config', '{"apiToken":null}'],
'should be very nice and support cli prefixed env var for key as well since it is an easy mistake to make',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {
SOCKET_CLI_API_KEY: 'abc'
})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: abc

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: abc')).toBe(true)
}
)

cmdit(
[
'config',
'get',
'apiToken',
'--config',
'{"apiToken":"ignoremebecausetheenvvarshouldbemoreimportant"}'
],
'should use the env var token when the config override also has a token set',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {
SOCKET_CLI_API_KEY: 'abc'
})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: abc

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: abc')).toBe(true)
}
)

cmdit(
[
'config',
'get',
'apiToken',
'--config',
'{"apiToken":"pickmepickme"}'
],
'should use the config override when there is no env var',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: pickmepickme

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: pickmepickme')).toBe(true)
}
)

cmdit(
['config', 'get', 'apiToken', '--config', '{}'],
'should yield no token when override has none',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {})
expect(stdout).toMatchInlineSnapshot(
`
"apiToken: undefined

Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag."
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config get\`, cwd: <redacted>"
`)

expect(stdout.includes('apiToken: undefined')).toBe(true)
}
)
})
})
})
37 changes: 30 additions & 7 deletions src/commands/config/cmd-config.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import path from 'node:path'

import { describe, expect } from 'vitest'
import { describe, expect, it } from 'vitest'

import constants from '../../../dist/constants.js'
import { cmdit, invokeNpm } from '../../../test/utils'
Expand Down Expand Up @@ -39,12 +39,12 @@ describe('socket config', async () => {
`
)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config\`, cwd: <redacted>"
`)
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket config\`, cwd: <redacted>"
`)

expect(code, 'help should exit with code 2').toBe(2)
expect(stderr, 'banner includes base command').toContain(
Expand Down Expand Up @@ -72,4 +72,27 @@ describe('socket config', async () => {
expect(code, 'dry-run should exit with code 0 if input ok').toBe(0)
}
)

describe('config override', () => {
cmdit(
['config', 'get', 'apiToken', '--config', '{apiToken:invalidjson}'],
'should print nice error when config override cannot be parsed',
async cmd => {
const { code, stderr, stdout } = await invokeNpm(entryPath, cmd, {})
expect(stdout).toMatchInlineSnapshot(`""`)
expect(`\n ${stderr}`).toMatchInlineSnapshot(`
"
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver <redacted>
|__ | . | _| '_| -_| _| | Node: <redacted>, API token set: <redacted>
|_____|___|___|_,_|___|_|.dev | Command: \`socket\`, cwd: <redacted>

\\x1b[31m\\xd7\\x1b[39m Could not JSON parse the config override. Make sure it's a proper JSON object (double-quoted keys and strings, no unquoted \`undefined\`) and try again."
`)

expect(stderr.includes('Could not JSON parse')).toBe(true)
expect(code, 'bad config input should exit with code 2 ').toBe(2)
}
)
})
})
5 changes: 3 additions & 2 deletions src/commands/config/handle-config-get.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { outputConfigGet } from './output-config-get'
import { getConfigValue } from '../../utils/config'
import { getConfigValue, isReadOnlyConfig } from '../../utils/config'

import type { LocalConfig } from '../../utils/config'

Expand All @@ -11,6 +11,7 @@ export async function handleConfigGet({
outputKind: 'json' | 'markdown' | 'text'
}) {
const value = getConfigValue(key)
const readOnly = isReadOnlyConfig()

await outputConfigGet(key, value, outputKind)
await outputConfigGet(key, value, readOnly, outputKind)
}
6 changes: 4 additions & 2 deletions src/commands/config/handle-config-set.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { outputConfigSet } from './output-config-set'
import { updateConfigValue } from '../../utils/config'
import { isReadOnlyConfig, updateConfigValue } from '../../utils/config'

import type { LocalConfig } from '../../utils/config'

Expand All @@ -13,5 +13,7 @@ export async function handleConfigSet({
value: string
}) {
updateConfigValue(key, value)
await outputConfigSet(key, value, outputKind)
const readOnly = isReadOnlyConfig()

await outputConfigSet(key, value, readOnly, outputKind)
}
17 changes: 16 additions & 1 deletion src/commands/config/output-config-get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,30 @@ import { LocalConfig } from '../../utils/config'
export async function outputConfigGet(
key: keyof LocalConfig,
value: unknown,
readOnly: boolean, // Is config in read-only mode? (Overrides applied)
outputKind: 'json' | 'markdown' | 'text'
) {
if (outputKind === 'json') {
logger.log(JSON.stringify({ success: true, result: { key, value } }))
logger.log(
JSON.stringify({ success: true, result: { key, value }, readOnly })
)
} else if (outputKind === 'markdown') {
logger.log(`# Config Value`)
logger.log('')
logger.log(`Config key '${key}' has value '${value}`)
if (readOnly) {
logger.log('')
logger.log(
'Note: the config is in read-only mode, meaning at least one key was temporarily\n overridden from an env var or command flag.'
)
}
} else {
logger.log(`${key}: ${value}`)
if (readOnly) {
logger.log('')
logger.log(
'Note: the config is in read-only mode, meaning at least one key was temporarily overridden from an env var or command flag.'
)
}
}
}
11 changes: 10 additions & 1 deletion src/commands/config/output-config-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'

import {
getConfigValue,
isReadOnlyConfig,
sensitiveConfigKeys,
supportedConfigKeys
} from '../../utils/config'
Expand All @@ -13,6 +14,7 @@ export async function outputConfigList({
full: boolean
outputKind: 'json' | 'markdown' | 'text'
}) {
const readOnly = isReadOnlyConfig()
if (outputKind === 'json') {
const obj: Record<string, unknown> = {}
for (const key of supportedConfigKeys.keys()) {
Expand All @@ -29,7 +31,8 @@ export async function outputConfigList({
{
success: true,
full,
config: obj
config: obj,
readOnly
},
null,
2
Expand All @@ -56,5 +59,11 @@ export async function outputConfigList({
)
}
}
if (readOnly) {
logger.log('')
logger.log(
'Note: the config is in read-only mode, meaning at least one key was temporarily\n overridden from an env var or command flag.'
)
}
}
}
Loading