@@ -31,6 +31,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'
3131import { naturalCompare } from '@socketsecurity/registry/lib/sorts'
3232
3333import { debugConfig } from './debug.mts'
34+ import { getEditableJsonClass } from './editable-json.mts'
3435import constants , {
3536 CONFIG_KEY_API_BASE_URL ,
3637 CONFIG_KEY_API_PROXY ,
@@ -98,17 +99,18 @@ function getConfigValues(): LocalConfig {
9899 _cachedConfig = { } as LocalConfig
99100 const { socketAppDataPath } = constants
100101 if ( socketAppDataPath ) {
101- const raw = safeReadFileSync ( socketAppDataPath )
102+ const configFilePath = path . join ( socketAppDataPath , 'config.json' )
103+ const raw = safeReadFileSync ( configFilePath )
102104 if ( raw ) {
103105 try {
104106 Object . assign (
105107 _cachedConfig ,
106108 JSON . parse ( Buffer . from ( raw , 'base64' ) . toString ( ) ) ,
107109 )
108- debugConfig ( socketAppDataPath , true )
110+ debugConfig ( configFilePath , true )
109111 } catch ( e ) {
110- logger . warn ( `Failed to parse config at ${ socketAppDataPath } ` )
111- debugConfig ( socketAppDataPath , false , e )
112+ logger . warn ( `Failed to parse config at ${ configFilePath } ` )
113+ debugConfig ( configFilePath , false , e )
112114 }
113115 // Normalize apiKey to apiToken and persist it.
114116 // This is a one time migration per user.
@@ -118,7 +120,7 @@ function getConfigValues(): LocalConfig {
118120 updateConfigValue ( CONFIG_KEY_API_TOKEN , token )
119121 }
120122 } else {
121- mkdirSync ( path . dirname ( socketAppDataPath ) , { recursive : true } )
123+ mkdirSync ( socketAppDataPath , { recursive : true } )
122124 }
123125 }
124126 }
@@ -243,6 +245,16 @@ let _cachedConfig: LocalConfig | undefined
243245// When using --config or SOCKET_CLI_CONFIG, do not persist the config.
244246let _configFromFlag = false
245247
248+ /**
249+ * Reset config cache for testing purposes.
250+ * This allows tests to start with a fresh config state.
251+ * @internal
252+ */
253+ export function resetConfigForTesting ( ) : void {
254+ _cachedConfig = undefined
255+ _configFromFlag = false
256+ }
257+
246258export function overrideCachedConfig ( jsonConfig : unknown ) : CResult < undefined > {
247259 debugFn ( 'notice' , 'override: full config (not stored)' )
248260
@@ -338,13 +350,44 @@ export function updateConfigValue<Key extends keyof LocalConfig>(
338350
339351 if ( ! _pendingSave ) {
340352 _pendingSave = true
353+ // Capture the current config state to save.
354+ const configToSave = { ...localConfig }
341355 process . nextTick ( ( ) => {
342356 _pendingSave = false
343357 const { socketAppDataPath } = constants
344358 if ( socketAppDataPath ) {
359+ mkdirSync ( socketAppDataPath , { recursive : true } )
360+ const configFilePath = path . join ( socketAppDataPath , 'config.json' )
361+ // Read existing file to preserve formatting, then update with new values.
362+ const existingRaw = safeReadFileSync ( configFilePath )
363+ const EditableJson = getEditableJsonClass < LocalConfig > ( )
364+ const editor = new EditableJson ( )
365+ if ( existingRaw !== undefined ) {
366+ const rawString = Buffer . isBuffer ( existingRaw )
367+ ? existingRaw . toString ( 'utf8' )
368+ : existingRaw
369+ try {
370+ const decoded = Buffer . from ( rawString , 'base64' ) . toString ( 'utf8' )
371+ editor . fromJSON ( decoded )
372+ } catch {
373+ // If decoding fails, start fresh.
374+ }
375+ } else {
376+ // Initialize empty editor for new file.
377+ editor . create ( configFilePath )
378+ }
379+ // Update with the captured config state.
380+ editor . update ( configToSave )
381+ // Get content with formatting symbols stripped.
382+ const contentToSave = Object . fromEntries (
383+ Object . entries ( editor . content ) . filter (
384+ ( [ key ] ) => typeof key === 'string' ,
385+ ) ,
386+ )
387+ const jsonContent = JSON . stringify ( contentToSave )
345388 writeFileSync (
346- socketAppDataPath ,
347- Buffer . from ( JSON . stringify ( localConfig ) ) . toString ( 'base64' ) ,
389+ configFilePath ,
390+ Buffer . from ( jsonContent ) . toString ( 'base64' ) ,
348391 )
349392 }
350393 } )
0 commit comments