@@ -279,11 +279,10 @@ export function readConfig(client: string, local?: boolean): ClientConfig {
279279 rawConfig = ( yaml . load ( fileContent ) as ClientConfig ) || { }
280280 } else if ( configPath . format === 'toml' ) {
281281 rawConfig = TOML . parse ( fileContent ) as ClientConfig
282- } else if ( configPath . path . endsWith ( '.jsonc' ) ) {
283- // Use jsonc-parser for .jsonc files to support comments
284- rawConfig = jsonc . parse ( fileContent ) as ClientConfig
285282 } else {
286- rawConfig = JSON . parse ( fileContent )
283+ // Always use jsonc-parser for JSON files to support comments
284+ // This handles both .json and .jsonc files with comments
285+ rawConfig = jsonc . parse ( fileContent ) as ClientConfig
287286 }
288287
289288 verbose ( `Config loaded successfully: ${ JSON . stringify ( rawConfig , null , 2 ) } ` )
@@ -319,6 +318,26 @@ export function writeConfig(config: ClientConfig, client?: string, local?: boole
319318 writeConfigFile ( config , configPath )
320319}
321320
321+ // Detect indentation style from JSON content using jsonc-parser
322+ function detectIndent ( text : string ) : { tabSize : number ; insertSpaces : boolean } {
323+ let result : { tabSize : number ; insertSpaces : boolean } | null = null
324+
325+ jsonc . visit ( text , {
326+ onObjectProperty : ( _property , offset , _length , startLine , startCharacter ) => {
327+ if ( result === null && startLine > 0 && startCharacter > 0 ) {
328+ const lineStart = text . lastIndexOf ( '\n' , offset - 1 ) + 1
329+ const whitespace = text . slice ( lineStart , offset )
330+ result = {
331+ tabSize : startCharacter ,
332+ insertSpaces : ! whitespace . includes ( '\t' ) ,
333+ }
334+ }
335+ } ,
336+ } )
337+
338+ return result || { tabSize : 2 , insertSpaces : true }
339+ }
340+
322341// Helper function for deep merge
323342function deepMerge ( target : ClientConfig , source : ClientConfig ) : ClientConfig {
324343 const result = { ...target }
@@ -356,11 +375,9 @@ function writeConfigFile(config: ClientConfig, target: ClientFileTarget): void {
356375 existingConfig = ( yaml . load ( originalFileContent ) as ClientConfig ) || { }
357376 } else if ( target . format === 'toml' ) {
358377 existingConfig = TOML . parse ( originalFileContent ) as ClientConfig
359- } else if ( target . path . endsWith ( '.jsonc' ) ) {
360- // Use jsonc-parser for .jsonc files to support comments
361- existingConfig = jsonc . parse ( originalFileContent ) as ClientConfig
362378 } else {
363- existingConfig = JSON . parse ( originalFileContent )
379+ // Always use jsonc-parser for JSON files to support comments
380+ existingConfig = jsonc . parse ( originalFileContent ) as ClientConfig
364381 }
365382
366383 verbose ( `Existing config loaded: ${ JSON . stringify ( existingConfig , null , 2 ) } ` )
@@ -385,24 +402,16 @@ function writeConfigFile(config: ClientConfig, target: ClientFileTarget): void {
385402 } )
386403 } else if ( target . format === 'toml' ) {
387404 configContent = TOML . stringify ( mergedConfig )
388- } else if ( target . path . endsWith ( '.jsonc' ) && originalFileContent ) {
389- // For .jsonc files, try to preserve comments and formatting using jsonc-parser
405+ } else if ( originalFileContent ) {
406+ // For JSON/JSONC files with existing content, use jsonc-parser to preserve comments
390407 try {
391- // Apply modifications to preserve existing structure
392- const editedContent = originalFileContent
393- const modifications : Array < jsonc . Edit > = [ ]
394-
395- // Generate edit operations for each key in the merged config
396- for ( const key of Object . keys ( mergedConfig ) ) {
397- const path = [ key ]
398- const edits = jsonc . modify ( editedContent , path , mergedConfig [ key ] , {
399- formattingOptions : { tabSize : 2 , insertSpaces : true } ,
400- } )
401- modifications . push ( ...edits )
402- }
403-
404- // Apply all edits
405- configContent = jsonc . applyEdits ( originalFileContent , modifications )
408+ // Only modify the specific configKey path, preserving everything else
409+ const configKeyPath = target . configKey . split ( '.' )
410+ const newValue = getNestedValue ( mergedConfig , target . configKey )
411+ const edits = jsonc . modify ( originalFileContent , configKeyPath , newValue , {
412+ formattingOptions : detectIndent ( originalFileContent ) ,
413+ } )
414+ configContent = jsonc . applyEdits ( originalFileContent , edits )
406415 } catch ( error ) {
407416 // Fallback to standard JSON.stringify if edit fails
408417 verbose ( `Error applying JSONC edits: ${ error instanceof Error ? error . message : String ( error ) } ` )
0 commit comments