@@ -82,14 +82,8 @@ export class JsonInsertNode extends ExecutableNode {
8282 try {
8383 const { json, path, value } = context . inputs ;
8484
85- // Handle null or undefined inputs
86- if ( json === null || json === undefined ) {
87- return this . createSuccessResult ( {
88- result : null ,
89- success : false ,
90- inserted : false ,
91- } ) ;
92- }
85+ // Initialize empty object when input is null/undefined
86+ const base = json === null || json === undefined ? { } : json ;
9387
9488 if ( path === null || path === undefined || path === "" ) {
9589 return this . createSuccessResult ( {
@@ -100,27 +94,15 @@ export class JsonInsertNode extends ExecutableNode {
10094 }
10195
10296 // Deep clone the input JSON to avoid modifying the original
103- const result = JSON . parse ( JSON . stringify ( json ) ) ;
104-
105- // Check if path already exists
106- const pathExists = this . pathExists ( result , path ) ;
107-
108- if ( pathExists ) {
109- // Path exists, don't insert
110- return this . createSuccessResult ( {
111- result,
112- success : true ,
113- inserted : false ,
114- } ) ;
115- }
97+ const result = JSON . parse ( JSON . stringify ( base ) ) ;
11698
117- // Path doesn't exist, insert the value
99+ // Insert or overwrite the value at path (upsert semantics)
118100 const success = this . insertValueAtPath ( result , path , value ) ;
119101
120102 return this . createSuccessResult ( {
121- result : success ? result : json ,
103+ result : success ? result : base ,
122104 success,
123- inserted : success ,
105+ inserted : true ,
124106 } ) ;
125107 } catch ( err ) {
126108 const error = err as Error ;
@@ -152,10 +134,11 @@ export class JsonInsertNode extends ExecutableNode {
152134 if ( ! Array . isArray ( current ) ) {
153135 return false ;
154136 }
155- if ( part < 0 || part >= current . length ) {
137+ const actualIndex = part < 0 ? current . length + part : part ;
138+ if ( actualIndex < 0 || actualIndex >= current . length ) {
156139 return false ;
157140 }
158- current = current [ part ] ;
141+ current = current [ actualIndex ] ;
159142 }
160143 }
161144
@@ -211,29 +194,25 @@ export class JsonInsertNode extends ExecutableNode {
211194 }
212195 }
213196
214- // Insert the value at the final path part
197+ // Insert the value at the final path part (overwrite if exists)
215198 const finalPart = pathParts [ pathParts . length - 1 ] ;
216199 if ( typeof finalPart === "string" ) {
217200 if ( typeof current !== "object" || current === null ) {
218201 return false ;
219202 }
220- // Only insert if the key doesn't exist
221- if ( ! ( finalPart in current ) ) {
222- current [ finalPart ] = value ;
223- return true ;
224- }
203+ current [ finalPart ] = value ;
204+ return true ;
225205 } else if ( typeof finalPart === "number" ) {
226206 if ( ! Array . isArray ( current ) ) {
227207 return false ;
228208 }
229- // Only insert if the index doesn't exist
230- if ( finalPart >= current . length ) {
231- while ( current . length <= finalPart ) {
232- current . push ( null ) ;
233- }
234- current [ finalPart ] = value ;
235- return true ;
209+ const actualIndex =
210+ finalPart < 0 ? current . length + finalPart : finalPart ;
211+ while ( current . length <= actualIndex ) {
212+ current . push ( null ) ;
236213 }
214+ current [ actualIndex ] = value ;
215+ return true ;
237216 }
238217
239218 return false ;
@@ -265,7 +244,7 @@ export class JsonInsertNode extends ExecutableNode {
265244 }
266245
267246 // Check for object property
268- const propMatch = remaining . match ( / ^ ( [ a - z A - Z _ ] [ a - z A - Z 0 - 9 _ ] * ) / ) ;
247+ const propMatch = remaining . match ( / ^ ( [ a - z A - Z _ ] [ a - z A - Z 0 - 9 _ - ] * ) / ) ;
269248 if ( propMatch ) {
270249 parts . push ( propMatch [ 1 ] ) ;
271250 remaining = remaining . substring ( propMatch [ 1 ] . length ) ;
0 commit comments