diff --git a/apps/api/src/app/services/sf-misc.ts b/apps/api/src/app/services/sf-misc.ts index 2717fb3fe..674cad00b 100644 --- a/apps/api/src/app/services/sf-misc.ts +++ b/apps/api/src/app/services/sf-misc.ts @@ -1,7 +1,7 @@ -import { ensureArray, orderObjectsBy } from '@jetstream/shared/utils'; +import { ensureArray, getFullNameFromListMetadata, orderObjectsBy } from '@jetstream/shared/utils'; import { ListMetadataResult, MapOf } from '@jetstream/types'; import type { PackageTypeMembers, RetrieveRequest } from 'jsforce'; -import { get as lodashGet, isObjectLike, isString } from 'lodash'; +import { isObjectLike, isString, get as lodashGet } from 'lodash'; import { create as xmlBuilder } from 'xmlbuilder2'; import { UserFacingError } from '../utils/error-handler'; @@ -15,8 +15,14 @@ export function buildPackageXml(types: MapOf, version: str Object.keys(types).forEach((metadataType) => { const typesNode = packageNode.ele('types'); if (types[metadataType].length) { - orderObjectsBy(types[metadataType], 'fullName').forEach(({ fullName }) => { - typesNode.ele('members').txt(fullName); + orderObjectsBy(types[metadataType], 'fullName').forEach(({ fullName, namespacePrefix }) => { + typesNode.ele('members').txt( + getFullNameFromListMetadata({ + fullName, + metadataType, + namespace: namespacePrefix, + }) + ); }); typesNode.ele('name').txt(metadataType); } @@ -42,7 +48,13 @@ export function getRetrieveRequestFromListMetadata(types: MapOf { const members = types[metadataName]; return { - members: members.map(({ fullName }) => fullName), + members: members.map(({ fullName, namespacePrefix }) => { + return getFullNameFromListMetadata({ + fullName, + metadataType: metadataName, + namespace: namespacePrefix, + }); + }), name: metadataName, }; }), diff --git a/libs/shared/utils/src/lib/__tests__/utils.spec.ts b/libs/shared/utils/src/lib/__tests__/utils.spec.ts index 6ddaa2f86..a781a0d13 100644 --- a/libs/shared/utils/src/lib/__tests__/utils.spec.ts +++ b/libs/shared/utils/src/lib/__tests__/utils.spec.ts @@ -1,4 +1,4 @@ -import { getExcelSafeSheetName } from '../utils'; +import { getExcelSafeSheetName, getFullNameFromListMetadata } from '../utils'; describe('utils.getExcelSafeSheetName', () => { it('should handle simple cases', () => { @@ -37,3 +37,42 @@ describe('utils.getExcelSafeSheetName', () => { ).toEqual('recordsrecordsrecordsrecordsr13'); }); }); + +describe('utils.getFullNameFromListMetadata', () => { + it('Should convert layout name', () => { + expect( + getFullNameFromListMetadata({ + fullName: 'SBQQ__AttributeSet__c-Attribute Set Layout', + metadataType: 'Layout', + namespace: 'SBQQ', + }) + ).toEqual('SBQQ__AttributeSet__c-SBQQ__Attribute Set Layout'); + }); + it('Should not double add namespace if already correct', () => { + expect( + getFullNameFromListMetadata({ + fullName: 'SBQQ__AttributeSet__c-SBQQ__Attribute Set Layout', + metadataType: 'Layout', + namespace: 'SBQQ', + }) + ).toEqual('SBQQ__AttributeSet__c-SBQQ__Attribute Set Layout'); + }); + it('Should not add namespace if non-managed', () => { + expect( + getFullNameFromListMetadata({ + fullName: 'AttributeSet__c-Attribute Set Layout', + metadataType: 'Layout', + namespace: null, + }) + ).toEqual('AttributeSet__c-Attribute Set Layout'); + }); + it('Should not apply to other managed package types', () => { + expect( + getFullNameFromListMetadata({ + fullName: 'AttributeSet__c-Attribute Set Layout', + metadataType: 'ApexClass', + namespace: 'TEST', + }) + ).toEqual('AttributeSet__c-Attribute Set Layout'); + }); +}); diff --git a/libs/shared/utils/src/lib/utils.ts b/libs/shared/utils/src/lib/utils.ts index 03708060b..c6d6a08fe 100644 --- a/libs/shared/utils/src/lib/utils.ts +++ b/libs/shared/utils/src/lib/utils.ts @@ -819,3 +819,24 @@ export function decodeHtmlEntity(value: Maybe) { .replaceAll('<', '<') .replaceAll('>', '>'); } + +/** + * Some fullNames from listMetadata need to be modified + */ +export function getFullNameFromListMetadata({ + metadataType, + namespace, + fullName, +}: { + metadataType: string; + fullName: string; + namespace: Maybe; +}) { + // Fix fullName for managed package layouts + if (namespace && metadataType === 'Layout' && !fullName.slice(fullName.indexOf('-') + 1).startsWith(`${namespace}__`)) { + const objectName = fullName.slice(0, fullName.indexOf('-') + 1); + const layoutName = fullName.slice(fullName.indexOf('-') + 1); + return `${objectName}${namespace}__${layoutName}`; + } + return fullName; +}