@@ -8,6 +8,7 @@ import detectIndent from 'detect-indent';
88import { Project } from '../entities/project.js' ;
99import { ProjectConfig } from '../entities/project-config.js' ;
1010import { prettyFormatFileDiff } from '../ui/file-diff-pretty-printer.js' ;
11+ import { deepEqual } from './index.js' ;
1112
1213export enum ModificationType {
1314 INSERT_OR_UPDATE ,
@@ -50,15 +51,20 @@ export class FileModificationCalculator {
5051
5152 // Reverse the traversal order so we edit from the back. This way the line numbers won't be messed up with new edits.
5253 for ( const existing of this . existingConfigs . reverse ( ) ) {
53- const duplicateIndex = modifications . findIndex ( ( modified ) => existing . isSameOnSystem ( modified . resource ) )
54+ const duplicateIndex = updateCache . findIndex ( ( modified ) => existing . isSameOnSystem ( modified . resource ) )
5455
55- // The resource was not modified in any way. Skip.
56+ // The existing was not modified in any way. Skip.
5657 if ( duplicateIndex === - 1 ) {
5758 continue ;
5859 }
60+
61+ const modified = updateCache [ duplicateIndex ] ;
5962 updateCache . splice ( duplicateIndex , 1 )
6063
61- const modified = modifications [ duplicateIndex ] ;
64+ if ( deepEqual ( modified . resource . parameters , existing . parameters ) ) {
65+ continue ;
66+ }
67+
6268 const duplicateSourceKey = existing . sourceMapKey ?. split ( '#' ) . at ( 1 ) ! ;
6369 const sourceIndex = Number . parseInt ( duplicateSourceKey . split ( '/' ) . at ( 1 ) ! )
6470
@@ -71,7 +77,7 @@ export class FileModificationCalculator {
7177
7278 // Update an existing resource
7379 newFile = this . remove ( newFile , this . sourceMap , sourceIndex ) ;
74- newFile = this . update ( newFile , modified . resource , this . sourceMap , sourceIndex ) ;
80+ newFile = this . update ( newFile , modified . resource , existing , this . sourceMap , sourceIndex ) ;
7581 }
7682
7783 // Insert new resources
@@ -82,6 +88,10 @@ export class FileModificationCalculator {
8288
8389 newFile = this . insert ( newFile , newResourcesToInsert , insertionIndex ) ;
8490
91+ const lastCharacterIndex = this . existingFile . contents . lastIndexOf ( ']' )
92+ const ending = this . existingFile . contents . slice ( Math . min ( lastCharacterIndex + 1 , this . existingFile . contents . length - 1 ) ) ;
93+ newFile += ending ;
94+
8595 return {
8696 newFile : newFile ,
8797 diff : prettyFormatFileDiff ( this . existingFile . contents , newFile ) ,
@@ -128,7 +138,9 @@ export class FileModificationCalculator {
128138 let result = file ;
129139
130140 for ( const newResource of resources . reverse ( ) ) {
131- let content = JSON . stringify ( newResource . raw , null , 2 ) ;
141+ const sortedResource = { ...newResource . core ( true ) , ...this . sortKeys ( newResource . parameters ) }
142+ let content = JSON . stringify ( sortedResource , null , 2 ) ;
143+
132144 content = content . split ( / \n / ) . map ( ( l ) => `${ this . indentString } ${ l } ` ) . join ( '\n' )
133145 content = `,\n${ content } ` ;
134146
@@ -167,20 +179,21 @@ export class FileModificationCalculator {
167179 private update (
168180 file : string ,
169181 resource : ResourceConfig ,
182+ existing : ResourceConfig ,
170183 sourceMap : SourceMap ,
171184 sourceIndex : number ,
172185 ) : string {
173186 // Updates: for now let's remove and re-add the entire object. Only two formatting availalbe either same line or multi-line
174187 const { value, valueEnd } = this . sourceMap . lookup ( `/${ sourceIndex } ` ) ! ;
175188 const isSameLine = value . line === valueEnd . line ;
176-
177- const isLast = sourceIndex === this . totalConfigLength - 1 ;
178189 const isFirst = sourceIndex === 0 ;
179190
180191 // We try to start deleting from the previous element to the next element if possible. This covers any spaces as well.
181192 const start = ! isFirst ? this . sourceMap . lookup ( `/${ sourceIndex - 1 } ` ) ?. valueEnd : this . sourceMap . lookup ( `/${ sourceIndex } ` ) ?. value ;
182193
183- let content = isSameLine ? JSON . stringify ( resource . raw ) : JSON . stringify ( resource . raw , null , this . indentString ) ;
194+ const sortedResource = this . sortKeys ( resource . raw , existing . raw ) ;
195+
196+ let content = isSameLine ? JSON . stringify ( sortedResource ) : JSON . stringify ( sortedResource , null , this . indentString ) ;
184197 content = this . updateParamsToOnelineIfNeeded ( content , sourceMap , sourceIndex ) ;
185198
186199 content = content . split ( / \n / ) . map ( ( l ) => `${ this . indentString } ${ l } ` ) . join ( '\n' ) ;
@@ -216,12 +229,18 @@ export class FileModificationCalculator {
216229 return s . substring ( 0 , start ) + s . substring ( end ) ;
217230 }
218231
219- /** Transforms a source key from global to file specific */
220- private transformSourceKey ( key : string ) : string {
221- return key . split ( '#' ) . at ( 1 ) ! ;
222- }
223-
224232 private isResourceConfig ( config : ProjectConfig | ResourceConfig ) : config is ResourceConfig {
225233 return config instanceof ResourceConfig ;
226234 }
235+
236+ private sortKeys ( obj : Record < string , unknown > , referenceOrder ?: Record < string , unknown > ) : Record < string , unknown > {
237+ const reference = Object . keys ( referenceOrder
238+ ?? Object . fromEntries ( [ ...Object . keys ( obj ) ] . sort ( ) . map ( ( k ) => [ k , undefined ] ) )
239+ ) ;
240+
241+ return Object . fromEntries (
242+ Object . entries ( obj )
243+ . sort ( ( a , b ) => reference . indexOf ( a [ 0 ] ) - reference . indexOf ( b [ 0 ] ) )
244+ )
245+ }
227246}
0 commit comments