Skip to content
Merged
10 changes: 10 additions & 0 deletions METADATA_SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,4 @@
"path": "./node_modules/cz-conventional-changelog"
}
}
}
}
9 changes: 6 additions & 3 deletions src/client/metadataApiDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
7 changes: 2 additions & 5 deletions src/convert/metadataConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Promise<void>> = [];

Expand All @@ -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
Expand All @@ -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()) {
Expand Down
18 changes: 8 additions & 10 deletions src/resolve/adapters/decomposedSourceAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
@@ -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
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"name": "mdapiToSource",
"duration": 6807.484392000013
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"name": "mdapiToSource",
"duration": 6781.243828000006
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@
"name": "mdapiToSource",
"duration": 13979.638694000023
}
]
]
21 changes: 20 additions & 1 deletion test/resolve/sourceComponent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';

Expand Down Expand Up @@ -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(
Expand Down