diff --git a/METADATA_SUPPORT.md b/METADATA_SUPPORT.md index 35ec9b10dc..93809039da 100644 --- a/METADATA_SUPPORT.md +++ b/METADATA_SUPPORT.md @@ -531,14 +531,24 @@ v57 introduces the following new types. Here's their current level of support |Metadata Type|Support|Notes| |:---|:---|:---| |ActionableListDefinition|❌|Not supported, but support could be added| +|CampaignTemplateDefinition|❌|Not supported, but support could be added| |ClauseCatgConfiguration|❌|Not supported, but support could be added| +|DisclosureDefinition|❌|Not supported, but support could be added| +|DisclosureDefinitionVersion|❌|Not supported, but support could be added| |DisclosureType|❌|Not supported, but support could be added| |ExternalClientApplication|✅|| +|ExternalDocStorageConfig|❌|Not supported, but support could be added| +|Gear|❌|Not supported, but support could be added| |GearDescriptor|❌|Not supported, but support could be added| +|GearLifecycle|❌|Not supported, but support could be added| |GearRule|❌|Not supported, but support could be added| +|GearRuleTest|❌|Not supported, but support could be added| |IdentityProviderSettings|✅|| +|LightningPropertyTypeBundle|❌|Not supported, but support could be added (but not for tracking)| +|LocationUse|❌|Not supported, but support could be added| |OmniSupervisorConfig|❌|Not supported, but support could be added (but not for tracking)| |ProductSpecificationTypeDefinition|❌|Not supported, but support could be added| +|WaveAnalyticAssetCollection|❌|Not supported, but support could be added| ## Additional Types diff --git a/package.json b/package.json index 2c5649d26b..6ad4466763 100644 --- a/package.json +++ b/package.json @@ -123,4 +123,4 @@ "path": "./node_modules/cz-conventional-changelog" } } -} \ No newline at end of file +} diff --git a/src/client/metadataApiDeploy.ts b/src/client/metadataApiDeploy.ts index e930d6057f..fd0ee8d6ae 100644 --- a/src/client/metadataApiDeploy.ts +++ b/src/client/metadataApiDeploy.ts @@ -111,15 +111,18 @@ export class DeployResult implements MetadataTransferResult { } else { // components with children are already taken care of through the messages, // so don't walk their content directories. - if (content && !type.children) { + if ( + content && + (!type.children || Object.values(type.children.types).some((t) => t.unaddressableWithoutParent)) + ) { for (const filePath of component.walkContent()) { - const response = Object.assign({}, baseResponse, { filePath }) as FileResponse; + const response = { ...baseResponse, filePath } as FileResponse; responses.push(response); } } if (xml) { - const response = Object.assign({}, baseResponse, { filePath: xml }) as FileResponse; + const response = { ...baseResponse, filePath: xml } as FileResponse; responses.push(response); } } diff --git a/src/convert/metadataConverter.ts b/src/convert/metadataConverter.ts index f7a241bac1..c5272ee98b 100644 --- a/src/convert/metadataConverter.ts +++ b/src/convert/metadataConverter.ts @@ -43,7 +43,6 @@ export class MetadataConverter { (comps instanceof ComponentSet ? Array.from(comps.getSourceComponents()) : comps) as SourceComponent[] ).filter((comp) => comp.type.isAddressable !== false); - let manifestContents; const isSource = targetFormat === 'source'; const tasks: Array> = []; @@ -57,14 +56,13 @@ export class MetadataConverter { if (output.packageName) { cs.fullName = output.packageName; } - manifestContents = await cs.getPackageXml(); packagePath = this.getPackagePath(output); defaultDirectory = packagePath; writer = new StandardWriter(packagePath); if (!isSource) { const manifestPath = join(packagePath, MetadataConverter.PACKAGE_XML_FILE); tasks.push( - promises.writeFile(manifestPath, manifestContents), + promises.writeFile(manifestPath, await cs.getPackageXml()), ...cs.getTypesOfDestructiveChanges().map(async (destructiveChangesType) => // for each of the destructive changes in the component set, convert and write the correct metadata // to each manifest @@ -80,12 +78,11 @@ export class MetadataConverter { if (output.packageName) { cs.fullName = output.packageName; } - manifestContents = await cs.getPackageXml(); packagePath = this.getPackagePath(output); defaultDirectory = packagePath; writer = new ZipWriter(packagePath); if (!isSource) { - writer.addToZip(manifestContents, MetadataConverter.PACKAGE_XML_FILE); + writer.addToZip(await cs.getPackageXml(), MetadataConverter.PACKAGE_XML_FILE); // for each of the destructive changes in the component set, convert and write the correct metadata // to each manifest for (const destructiveChangeType of cs.getTypesOfDestructiveChanges()) { diff --git a/src/resolve/adapters/decomposedSourceAdapter.ts b/src/resolve/adapters/decomposedSourceAdapter.ts index 49da57c976..2940e8843b 100644 --- a/src/resolve/adapters/decomposedSourceAdapter.ts +++ b/src/resolve/adapters/decomposedSourceAdapter.ts @@ -86,7 +86,7 @@ export class DecomposedSourceAdapter extends MixedContentSourceAdapter { const triggerIsAChild = !!childTypeId; const strategy = this.type.strategies.decomposition; - if (triggerIsAChild) { + if (triggerIsAChild && !this.type.children.types[childTypeId].unaddressableWithoutParent) { if (strategy === DecompositionStrategy.FolderPerType || isResolvingSource) { let parent = component; if (!parent) { @@ -111,15 +111,13 @@ export class DecomposedSourceAdapter extends MixedContentSourceAdapter { this.forceIgnore ); } - } else { - if (!component) { - // This is most likely metadata found within a CustomObject folder that is not a - // child type of CustomObject. E.g., Layout, SharingRules, ApexClass. - throw new SfError( - messages.getMessage('error_unexpected_child_type', [trigger, this.type.name]), - 'TypeInferenceError' - ); - } + } else if (!component) { + // This is most likely metadata found within a CustomObject folder that is not a + // child type of CustomObject. E.g., Layout, SharingRules, ApexClass. + throw new SfError( + messages.getMessage('error_unexpected_child_type', [trigger, this.type.name]), + 'TypeInferenceError' + ); } if (component) { component.content = pathToContent; diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/eda.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/eda.json index d7a2b9d488..8705e1dfa6 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/eda.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/eda.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 325.82882699999027 + "duration": 329.62463900004514 }, { "name": "sourceToMdapi", - "duration": 7251.922354000009 + "duration": 7505.23844700004 }, { "name": "sourceToZip", - "duration": 5983.844335000002 + "duration": 6470.010548999999 }, { "name": "mdapiToSource", - "duration": 8623.723956000002 + "duration": 5877.771837000037 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClasses.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClasses.json index bab9d4631f..bd8ffac737 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClasses.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClasses.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 664.5060110000195 + "duration": 644.1402209999505 }, { "name": "sourceToMdapi", - "duration": 11993.994738000038 + "duration": 11856.592849999957 }, { "name": "sourceToZip", - "duration": 9293.955343000009 + "duration": 10338.099250999978 }, { "name": "mdapiToSource", - "duration": 10224.62978399999 + "duration": 8291.250971000001 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClassesOneDir.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClassesOneDir.json index 192a6f3670..9fe92f79b0 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClassesOneDir.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-CPU-E5-2673-v4-2-30GHz/lotsOfClassesOneDir.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 1084.5274579999968 + "duration": 1090.1220250000479 }, { "name": "sourceToMdapi", - "duration": 18790.406279999996 + "duration": 17970.10952900001 }, { "name": "sourceToZip", - "duration": 16412.87079200003 + "duration": 15943.596995999978 }, { "name": "mdapiToSource", - "duration": 16847.423238000018 + "duration": 14545.061661000014 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/eda.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/eda.json index 980a46ecd3..9b5cb649cb 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/eda.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/eda.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 218.47389499998826 + "duration": 227.84873699999298 }, { "name": "sourceToMdapi", - "duration": 5293.27240300001 + "duration": 5575.808999000001 }, { "name": "sourceToZip", - "duration": 4158.915987000015 + "duration": 5121.344982999988 }, { "name": "mdapiToSource", - "duration": 6551.467303000012 + "duration": 4306.255004000006 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClasses.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClasses.json index e36ee1c20e..88864c7f2e 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClasses.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClasses.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 431.3132029999979 + "duration": 464.14559599998756 }, { "name": "sourceToMdapi", - "duration": 8141.630254999996 + "duration": 8464.103521000012 }, { "name": "sourceToZip", - "duration": 6378.759560999984 + "duration": 7716.617144000018 }, { "name": "mdapiToSource", - "duration": 7380.699353000004 + "duration": 5273.308957000001 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClassesOneDir.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClassesOneDir.json index 8e93676913..1d50cf74dd 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClassesOneDir.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8272CL-CPU-2-60GHz/lotsOfClassesOneDir.json @@ -1,18 +1,18 @@ [ { "name": "componentSetCreate", - "duration": 764.7591390000016 + "duration": 782.2161900000065 }, { "name": "sourceToMdapi", - "duration": 11849.736803999986 + "duration": 12909.834803000005 }, { "name": "sourceToZip", - "duration": 10867.191843999986 + "duration": 11247.063521999982 }, { "name": "mdapiToSource", - "duration": 14328.787168999988 + "duration": 12979.326094000018 } ] \ No newline at end of file diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/eda.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/eda.json index 9259e63d78..e4a6d2f73d 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/eda.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/eda.json @@ -15,4 +15,4 @@ "name": "mdapiToSource", "duration": 6807.484392000013 } -] \ No newline at end of file +] diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClasses.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClasses.json index 68c2a2c3ba..cad20d624b 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClasses.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClasses.json @@ -15,4 +15,4 @@ "name": "mdapiToSource", "duration": 6781.243828000006 } -] \ No newline at end of file +] diff --git a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClassesOneDir.json b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClassesOneDir.json index 8b68ec2131..bbcf0c93c7 100644 --- a/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClassesOneDir.json +++ b/test/nuts/perfResults/x64-linux-2xIntel-Xeon-Platinum-8370C-CPU-2-80GHz/lotsOfClassesOneDir.json @@ -15,4 +15,4 @@ "name": "mdapiToSource", "duration": 13979.638694000023 } -] \ No newline at end of file +] diff --git a/test/resolve/sourceComponent.test.ts b/test/resolve/sourceComponent.test.ts index 6a56a83a9b..8aef95ffb9 100644 --- a/test/resolve/sourceComponent.test.ts +++ b/test/resolve/sourceComponent.test.ts @@ -8,7 +8,6 @@ import { join } from 'path'; import { assert, expect } from 'chai'; import { createSandbox } from 'sinon'; import { Messages, SfError } from '@salesforce/core'; - import { decomposed, matchingContentFile, mixedContentDirectory, xmlInFolder } from '../mock'; import { DECOMPOSED_COMPONENT } from '../mock/type-constants/customObjectConstant'; import { COMPONENT } from '../mock/type-constants/apexClassConstant'; @@ -32,6 +31,10 @@ import { SourceComponent, VirtualTreeContainer, } from '../../src'; +import { + DECOMPOSED_TOP_LEVEL_CHILD_XML_PATHS, + DECOMPOSED_TOP_LEVEL_COMPONENT, +} from '../mock/type-constants/customObjectTranslationConstant'; import { DecomposedSourceAdapter } from '../../src/resolve/adapters'; import { RegistryTestUtil } from './registryTestUtil'; @@ -423,6 +426,22 @@ describe('SourceComponent', () => { }); }); + describe('Un-addressable decomposed child (cot/cof)', () => { + it('gets parent when asked to resolve a child by filePath', () => { + const expectedTopLevel = DECOMPOSED_TOP_LEVEL_COMPONENT; + const adapter = new DecomposedSourceAdapter( + expectedTopLevel.type, + new RegistryAccess(), + undefined, + expectedTopLevel.tree + ); + + const result = adapter.getComponent(DECOMPOSED_TOP_LEVEL_CHILD_XML_PATHS[0], true); + expect(result.type).to.deep.equal(expectedTopLevel.type); + expect(result.xml).to.equal(expectedTopLevel.xml); + }); + }); + describe('Nondecomposed Child Components', () => { const type = registry.types.customlabels; const expectedChild = SourceComponent.createVirtualComponent(