Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 51 additions & 26 deletions api/src/utils/content-type-creator.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ function buildFieldSchema(item: any, marketPlacePath: string, parentUid = ''): a
data_type: "group",
display_name: item?.display_name || rawUid, // Keep original for display
field_metadata: {},
schema: groupSchema,
schema: removeDuplicateFields(groupSchema),
uid: itemUid, // Snake case uid
multiple: item?.advanced?.multiple || false,
mandatory: item?.advanced?.mandatory || false,
Expand Down Expand Up @@ -237,40 +237,50 @@ function getLastSegmentNew(str: string, separator: string): string {
return segments[segments.length - 1].trim();
}

export function buildSchemaTree(fields: any[], parentUid = '', parentType = ''): any[] {
export function buildSchemaTree(fields: any[], parentUid = '', parentType = '', oldParentUid = ''): any[] {

if (!Array.isArray(fields)) {
console.warn('buildSchemaTree called with invalid fields:', fields);
return [];
}
// Build a lookup map for O(1) access
const fieldMap = new Map<string, any>();
fields.forEach(f => {
if (f.contentstackFieldUid) {
fieldMap.set(f.contentstackFieldUid, f);
fields?.forEach(f => {
if (f?.contentstackFieldUid) {
fieldMap?.set(f?.contentstackFieldUid, f);
}
});

// Filter direct children of current parent
const directChildren = fields.filter(field => {
const fieldUid = field.contentstackFieldUid || '';
const fieldUid = field?.contentstackFieldUid || '';

if (!parentUid) {
// Root level - only fields without dots
return fieldUid && !fieldUid.includes('.');
return fieldUid && !fieldUid?.includes('.');
}

// Check if direct child of parent
if (!fieldUid.startsWith(parentUid + '.')) return false;
// Check if field is a direct child of parentUid
if (fieldUid?.startsWith(parentUid + '.')) {
const remainder = fieldUid?.substring(parentUid.length + 1);
// Verify it's exactly one level deeper (no more dots in remainder)
return remainder && !remainder?.includes('.');
}

// Fallback: check if field is a direct child of oldPrentUid (if provided and different)
if (oldParentUid && oldParentUid !== parentUid && fieldUid?.startsWith(oldParentUid + '.')) {
const remainder = fieldUid?.substring(oldParentUid.length + 1);
// Verify it's exactly one level deeper (no more dots in remainder)
return remainder && !remainder?.includes('.');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add null checks in above function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// Verify it's exactly one level deeper
const remainder = fieldUid.substring(parentUid.length + 1);
return remainder && !remainder.includes('.');
// Not a direct child
return false;
});

return directChildren.map(field => {
const uid = getLastSegmentNew(field.contentstackFieldUid, '.');
const displayName = field.display_name || getLastSegmentNew(field.contentstackField || '', '>').trim();
const uid = getLastSegmentNew(field?.contentstackFieldUid, '.');
const displayName = field?.display_name || getLastSegmentNew(field?.contentstackField || '', '>').trim();

// Base field structure
const result: any = {
Expand All @@ -280,14 +290,29 @@ export function buildSchemaTree(fields: any[], parentUid = '', parentType = ''):
};

// Determine if field should have nested schema
const fieldUid = field.contentstackFieldUid;
const fieldType = field.contentstackFieldType;

// Check if this field has children
const hasChildren = fields.some(f =>
f.contentstackFieldUid &&
f.contentstackFieldUid.startsWith(fieldUid + '.')
);
const fieldUid = field?.contentstackFieldUid;
const fieldType = field?.contentstackFieldType;
const oldFieldUid = field?.backupFieldUid;

// Check if this field has direct children (exactly one level deeper)
const hasChildren = fields.some(f => {
const fUid = f?.contentstackFieldUid || '';
if (!fUid) return false;

// Check if field starts with current fieldUid and is exactly one level deeper
if (fieldUid && fUid?.startsWith(fieldUid + '.')) {
const remainder = fUid?.substring(fieldUid.length + 1);
return remainder && !remainder?.includes('.');
}

// Check if field starts with oldFieldtUid and is exactly one level deeper
if (oldFieldUid && fUid?.startsWith(oldFieldUid + '.')) {
const remainder = fUid?.substring(oldFieldUid.length + 1);
return remainder && !remainder?.includes('.');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add null checks in above block

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


return false;
});

if (hasChildren) {
if (fieldType === 'modular_blocks') {
Expand All @@ -307,13 +332,13 @@ export function buildSchemaTree(fields: any[], parentUid = '', parentType = ''):
...child,
uid: childUid,
display_name: childDisplay,
schema: buildSchemaTree(fields, child.contentstackFieldUid, 'modular_blocks_child')
schema: buildSchemaTree(fields, child.contentstackFieldUid, 'modular_blocks_child', child?.backupFieldUid)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

child?.contentstackFieldUid

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want the backFieldUId to get the nested child of it if it is mapped to another field

};
});
} else if (fieldType === 'group' ||
(fieldType === 'modular_blocks_child' && hasChildren)) {
// Recursively build schema for groups and modular block children with nested content
result.schema = buildSchemaTree(fields, fieldUid, fieldType);
result.schema = buildSchemaTree(fields, fieldUid, fieldType, oldFieldUid);
}
}

Expand Down Expand Up @@ -996,7 +1021,7 @@ const mergeTwoCts = async (ct: any, mergeCts: any) => {
group?.push(fieldGp);
}
}
field.schema = [...field?.schema ?? [], ...group];
field.schema = removeDuplicateFields([...field?.schema ?? [], ...group]);
}
}
ctData.schema = await mergeArrays(ctData?.schema, mergeCts?.schema) ?? [];
Expand All @@ -1022,7 +1047,7 @@ export const contenTypeMaker = async ({ contentType, destinationStackId, project

// Safe: ensures we never pass undefined to the builder
const ctData: any[] = buildSchemaTree(contentType?.fieldMapping || []);

// Use the deep converter that properly handles groups & modular blocks
for (const item of ctData) {
if (item?.isDeleted === true) continue;
Expand Down