@@ -200,7 +200,7 @@ function buildFieldSchema(item: any, marketPlacePath: string, parentUid = ''): a
200200 data_type : "group" ,
201201 display_name : item ?. display_name || rawUid , // Keep original for display
202202 field_metadata : { } ,
203- schema : groupSchema ,
203+ schema : removeDuplicateFields ( groupSchema ) ,
204204 uid : itemUid , // Snake case uid
205205 multiple : item ?. advanced ?. multiple || false ,
206206 mandatory : item ?. advanced ?. mandatory || false ,
@@ -237,40 +237,50 @@ function getLastSegmentNew(str: string, separator: string): string {
237237 return segments [ segments . length - 1 ] . trim ( ) ;
238238}
239239
240- export function buildSchemaTree ( fields : any [ ] , parentUid = '' , parentType = '' ) : any [ ] {
240+ export function buildSchemaTree ( fields : any [ ] , parentUid = '' , parentType = '' , oldParentUid = '' ) : any [ ] {
241241
242242 if ( ! Array . isArray ( fields ) ) {
243243 console . warn ( 'buildSchemaTree called with invalid fields:' , fields ) ;
244244 return [ ] ;
245245 }
246246 // Build a lookup map for O(1) access
247247 const fieldMap = new Map < string , any > ( ) ;
248- fields . forEach ( f => {
249- if ( f . contentstackFieldUid ) {
250- fieldMap . set ( f . contentstackFieldUid , f ) ;
248+ fields ? .forEach ( f => {
249+ if ( f ? .contentstackFieldUid ) {
250+ fieldMap ? .set ( f ? .contentstackFieldUid , f ) ;
251251 }
252252 } ) ;
253253
254254 // Filter direct children of current parent
255255 const directChildren = fields . filter ( field => {
256- const fieldUid = field . contentstackFieldUid || '' ;
256+ const fieldUid = field ? .contentstackFieldUid || '' ;
257257
258258 if ( ! parentUid ) {
259259 // Root level - only fields without dots
260- return fieldUid && ! fieldUid . includes ( '.' ) ;
260+ return fieldUid && ! fieldUid ? .includes ( '.' ) ;
261261 }
262262
263- // Check if direct child of parent
264- if ( ! fieldUid . startsWith ( parentUid + '.' ) ) return false ;
263+ // Check if field is a direct child of parentUid
264+ if ( fieldUid ?. startsWith ( parentUid + '.' ) ) {
265+ const remainder = fieldUid ?. substring ( parentUid . length + 1 ) ;
266+ // Verify it's exactly one level deeper (no more dots in remainder)
267+ return remainder && ! remainder ?. includes ( '.' ) ;
268+ }
269+
270+ // Fallback: check if field is a direct child of oldPrentUid (if provided and different)
271+ if ( oldParentUid && oldParentUid !== parentUid && fieldUid ?. startsWith ( oldParentUid + '.' ) ) {
272+ const remainder = fieldUid ?. substring ( oldParentUid . length + 1 ) ;
273+ // Verify it's exactly one level deeper (no more dots in remainder)
274+ return remainder && ! remainder ?. includes ( '.' ) ;
275+ }
265276
266- // Verify it's exactly one level deeper
267- const remainder = fieldUid . substring ( parentUid . length + 1 ) ;
268- return remainder && ! remainder . includes ( '.' ) ;
277+ // Not a direct child
278+ return false ;
269279 } ) ;
270280
271281 return directChildren . map ( field => {
272- const uid = getLastSegmentNew ( field . contentstackFieldUid , '.' ) ;
273- const displayName = field . display_name || getLastSegmentNew ( field . contentstackField || '' , '>' ) . trim ( ) ;
282+ const uid = getLastSegmentNew ( field ? .contentstackFieldUid , '.' ) ;
283+ const displayName = field ? .display_name || getLastSegmentNew ( field ? .contentstackField || '' , '>' ) . trim ( ) ;
274284
275285 // Base field structure
276286 const result : any = {
@@ -280,14 +290,29 @@ export function buildSchemaTree(fields: any[], parentUid = '', parentType = ''):
280290 } ;
281291
282292 // Determine if field should have nested schema
283- const fieldUid = field . contentstackFieldUid ;
284- const fieldType = field . contentstackFieldType ;
285-
286- // Check if this field has children
287- const hasChildren = fields . some ( f =>
288- f . contentstackFieldUid &&
289- f . contentstackFieldUid . startsWith ( fieldUid + '.' )
290- ) ;
293+ const fieldUid = field ?. contentstackFieldUid ;
294+ const fieldType = field ?. contentstackFieldType ;
295+ const oldFieldUid = field ?. backupFieldUid ;
296+
297+ // Check if this field has direct children (exactly one level deeper)
298+ const hasChildren = fields . some ( f => {
299+ const fUid = f ?. contentstackFieldUid || '' ;
300+ if ( ! fUid ) return false ;
301+
302+ // Check if field starts with current fieldUid and is exactly one level deeper
303+ if ( fieldUid && fUid ?. startsWith ( fieldUid + '.' ) ) {
304+ const remainder = fUid ?. substring ( fieldUid . length + 1 ) ;
305+ return remainder && ! remainder ?. includes ( '.' ) ;
306+ }
307+
308+ // Check if field starts with oldFieldtUid and is exactly one level deeper
309+ if ( oldFieldUid && fUid ?. startsWith ( oldFieldUid + '.' ) ) {
310+ const remainder = fUid ?. substring ( oldFieldUid . length + 1 ) ;
311+ return remainder && ! remainder ?. includes ( '.' ) ;
312+ }
313+
314+ return false ;
315+ } ) ;
291316
292317 if ( hasChildren ) {
293318 if ( fieldType === 'modular_blocks' ) {
@@ -307,13 +332,13 @@ export function buildSchemaTree(fields: any[], parentUid = '', parentType = ''):
307332 ...child ,
308333 uid : childUid ,
309334 display_name : childDisplay ,
310- schema : buildSchemaTree ( fields , child . contentstackFieldUid , 'modular_blocks_child' )
335+ schema : buildSchemaTree ( fields , child . contentstackFieldUid , 'modular_blocks_child' , child ?. backupFieldUid )
311336 } ;
312337 } ) ;
313338 } else if ( fieldType === 'group' ||
314339 ( fieldType === 'modular_blocks_child' && hasChildren ) ) {
315340 // Recursively build schema for groups and modular block children with nested content
316- result . schema = buildSchemaTree ( fields , fieldUid , fieldType ) ;
341+ result . schema = buildSchemaTree ( fields , fieldUid , fieldType , oldFieldUid ) ;
317342 }
318343 }
319344
@@ -996,7 +1021,7 @@ const mergeTwoCts = async (ct: any, mergeCts: any) => {
9961021 group ?. push ( fieldGp ) ;
9971022 }
9981023 }
999- field . schema = [ ...field ?. schema ?? [ ] , ...group ] ;
1024+ field . schema = removeDuplicateFields ( [ ...field ?. schema ?? [ ] , ...group ] ) ;
10001025 }
10011026 }
10021027 ctData . schema = await mergeArrays ( ctData ?. schema , mergeCts ?. schema ) ?? [ ] ;
@@ -1022,7 +1047,7 @@ export const contenTypeMaker = async ({ contentType, destinationStackId, project
10221047
10231048 // Safe: ensures we never pass undefined to the builder
10241049 const ctData : any [ ] = buildSchemaTree ( contentType ?. fieldMapping || [ ] ) ;
1025-
1050+
10261051 // Use the deep converter that properly handles groups & modular blocks
10271052 for ( const item of ctData ) {
10281053 if ( item ?. isDeleted === true ) continue ;
0 commit comments