Skip to content

Commit

Permalink
refactor: first round of cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
WillieRuemmele committed Sep 5, 2024
1 parent bc10579 commit 36c5e1c
Show file tree
Hide file tree
Showing 5 changed files with 339 additions and 373 deletions.
98 changes: 25 additions & 73 deletions src/convert/transformers/decomposedPermissionSetTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,14 @@ export class DecomposedPermissionSetTransformer extends BaseMetadataTransformer

const childrenOfMergeComponent = new ComponentSet(mergeWith?.getChildren(), this.registry);
const composedMetadata = await getComposedMetadataEntries(component);
const parentXmlObject = buildParentXml(component.type)(composedMetadata);
const parentXmlObject: XmlObj = {
[component.type.name]: {
[XML_NS_KEY]: XML_NS_URL,
...Object.fromEntries(
composedMetadata.filter((v) => v.childTypeId === undefined).map(({ tagKey, tagValue }) => [tagKey, tagValue])
),
},
};
const stateSetter = setDecomposedState(this.context.decomposition.transactionState);

const writeInfosForChildren = composedMetadata
Expand All @@ -75,16 +82,14 @@ export class DecomposedPermissionSetTransformer extends BaseMetadataTransformer
.filter((c) => !c.childType.directoryName)
.map((c) => toInfoContainer(mergeWith)(component)(c.childType)(c.tagValue as JsonMap))
.filter(forceIgnoreAllowsComponent(forceIgnore))
.map(handleUnaddressableChildAlone(composedMetadata.length)(parentXmlObject)(stateSetter))
.flatMap(getChildWriteInfos(stateSetter)(childrenOfMergeComponent));

const toBeCombined = composedMetadata
.filter(hasChildTypeId)
.map(addChildType)
.filter((c) => c.childType.directoryName)
.map((c) => toInfoContainer(mergeWith)(component)(c.childType)(c.tagValue as JsonMap))
.filter(forceIgnoreAllowsComponent(forceIgnore))
.map(handleUnaddressableChildAlone(composedMetadata.length)(parentXmlObject)(stateSetter));
.filter(forceIgnoreAllowsComponent(forceIgnore));
const combined = getAndCombineChildWriteInfos(toBeCombined, stateSetter, childrenOfMergeComponent);
writeInfosForChildren.push(...combined);

Expand All @@ -96,69 +101,35 @@ export class DecomposedPermissionSetTransformer extends BaseMetadataTransformer

// files that exist in FS (therefore, in mergeWith) but aren't in the component should be deleted by returning a writeInfo
// only do this if all the children have isAddressable marked false
const writeInfosForMissingChildrenToDelete: WriteInfo[] =
mergeWith && allChildrenAreUnaddressable(component.type)
? childrenOfMergeComponent
.getSourceComponents()
.toArray()
.filter(hasXml)
.filter((c) => !childDestinations.has(c.xml))
.map((c) => ({ shouldDelete: true, output: c.xml, fullName: c.fullName, type: c.type.name }))
: [];
const writeInfosForMissingChildrenToDelete: WriteInfo[] = mergeWith
? childrenOfMergeComponent
.getSourceComponents()
.toArray()
.filter(hasXml)
.filter((c) => !childDestinations.has(c.xml))
.map((c) => ({ shouldDelete: true, output: c.xml, fullName: c.fullName, type: c.type.name }))
: [];

return [...writeInfosForChildren, ...writeInfoForParent, ...writeInfosForMissingChildrenToDelete];
}
}

const hasXml = (c: SourceComponent): c is SourceComponent & { xml: string } => typeof c.xml === 'string';

const allChildrenAreUnaddressable = (type: MetadataType): boolean =>
Object.values(type.children?.types ?? {}).every(
// exclude the COFT (unaddressableWithoutParent) from being deleted because its absence *might* not mean it was deleted from the org
(c) => c.isAddressable === false && c.unaddressableWithoutParent !== true
);

/**
* composedMetadata is a representation of the parent's xml
*
* if there is no CustomObjectTranslation in the org, the composedMetadata will be 2 entries
* the xml declaration, and a fields attribute, which points to the child CustomObjectFieldTranslation
*
* because CustomObjectFieldTranslation is the only metadata type with 'requiresParent' = true we can
* calculate if a CustomObjectTranslation was retrieved from the org (composedMetadata.length > 2), or,
* if we'll have to write an empty CustomObjectTranslation file (composedMetadata.length <=2).
*
* CustomObjectFieldTranslations are only addressable through their parent, and require a
* CustomObjectTranslation file to be present
*/
const handleUnaddressableChildAlone =
(composedMetadataLength: number) =>
(parentXmlObject: XmlObj) =>
(stateSetter: StateSetter) =>
(v: InfoContainer): InfoContainer => {
if (v.childComponent.type.unaddressableWithoutParent && composedMetadataLength <= 2) {
stateSetter(v.childComponent, {
writeInfo: {
source: new JsToXml(parentXmlObject),
output: getDefaultOutput(v.parentComponent),
},
});
}
return v;
};

const getChildWriteInfos =
(stateSetter: StateSetter) =>
(childrenOfMergeComponent: ComponentSet) =>
({ mergeWith, childComponent, value, entryName }: InfoContainer): WriteInfo[] => {
const childDirectories = childComponent.parent?.type.children?.directories as Record<string, string>;

// convert to the correct child's xml tag with capitalization
const source = objectToSource(childComponent.parent!.type.name)(
Object.entries(childDirectories)
.find((e) => e[1] === childComponent.type.name.toLowerCase())
?.at(0) ?? ''
)(value as unknown as JsonMap[]);
const source = new JsToXml({
[childComponent.parent!.type.name]: {
[Object.entries(childDirectories)
.find((e) => e[1] === childComponent.type.name.toLowerCase())
?.at(0) ?? '']: value,
},
});
// if there's nothing to merge with, push write operation now to default location
if (!mergeWith) {
return [{ source, output: getDefaultOutput(childComponent) }];
Expand Down Expand Up @@ -273,7 +244,7 @@ const getDefaultOutput = (component: MetadataComponent): SourcePath => {
// there could be a '.' inside the child name (ex: PermissionSet.FieldPermissions.field uses Obj__c.Field__c)
const childName = tail.length ? tail.join('.') : undefined;
const output = join(
parent?.type.strategies?.decomposition === 'filePerType' ? type.directoryName : '',
parent?.type.strategies?.decomposition ? type.directoryName : '',
`${childName ?? baseName}.${ensureString(component.type.suffix)}${META_XML_SUFFIX}`
);
// const output = join(type.directoryName, `${baseName}.${ensureString(component.type.suffix)}${META_XML_SUFFIX}`);
Expand Down Expand Up @@ -401,24 +372,5 @@ const forceIgnoreAllowsComponent =
(ic: InfoContainer): boolean =>
forceIgnore.accepts(getDefaultOutput(ic.childComponent));

/** wrap some xml in the Metadata type and add the NS stuff */
const objectToSource =
(parentType: string) =>
(childTypeName: string) =>
(obj: JsonMap[]): JsToXml =>
new JsToXml({ [parentType]: { [childTypeName]: obj } });

/** filter out the children and create the remaining parentXml */
const buildParentXml =
(parentType: MetadataType) =>
(c: ComposedMetadata[]): XmlObj => ({
[parentType.name]: {
[XML_NS_KEY]: XML_NS_URL,
...Object.fromEntries(
c.filter((v) => v.childTypeId === undefined).map(({ tagKey, tagValue }) => [tagKey, tagValue])
),
},
});

const getOutputFile = (component: SourceComponent, mergeWith?: SourceComponent): string =>
mergeWith?.xml ?? getDefaultOutput(component);
2 changes: 1 addition & 1 deletion src/convert/transformers/metadataTransformerFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class MetadataTransformerFactory {
return new StaticResourceMetadataTransformer(this.registry, this.context);
case 'nonDecomposed':
return new NonDecomposedMetadataTransformer(this.registry, this.context);
case 'filePerType':
case 'decomposedPermissionSet':
return new DecomposedPermissionSetTransformer(this.registry, this.context);
case 'decomposedLabels':
return component.type.name === 'CustomLabels'
Expand Down
6 changes: 3 additions & 3 deletions src/registry/presets/decomposePermissionSetBeta2.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
"id": "objectsettings",
"name": "ObjectSettings",
"directoryName": "objectSettings",
"suffix": "objectsettings",
"suffix": "objectSettings",
"isAddressable": false
},
"fieldpermission": {
Expand Down Expand Up @@ -187,9 +187,9 @@
"inFolder": false,
"name": "PermissionSet",
"strategies": {
"decomposition": "filePerType",
"decomposition": "topLevel",
"adapter": "decomposed",
"transformer": "filePerType"
"transformer": "decomposedPermissionSet"
},
"strictDirectoryName": true,
"suffix": "permissionset",
Expand Down
10 changes: 8 additions & 2 deletions src/registry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,14 @@ export type MetadataType = {
*/
strategies?: {
adapter: 'mixedContent' | 'matchingContentFile' | 'decomposed' | 'digitalExperience' | 'bundle' | 'default';
transformer?: 'decomposed' | 'staticResource' | 'nonDecomposed' | 'standard' | 'decomposedLabels' | 'filePerType';
decomposition?: 'topLevel' | 'folderPerType' | 'filePerType';
transformer?:
| 'decomposed'
| 'staticResource'
| 'nonDecomposed'
| 'standard'
| 'decomposedLabels'
| 'decomposedPermissionSet';
decomposition?: 'topLevel' | 'folderPerType';
recomposition?: 'startEmpty';
};
};
Expand Down
Loading

2 comments on commit 36c5e1c

@svc-cli-bot
Copy link
Collaborator

Choose a reason for hiding this comment

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

Benchmark

Benchmark suite Current: 36c5e1c Previous: 12b5904 Ratio
eda-componentSetCreate-linux 244 ms 234 ms 1.04
eda-sourceToMdapi-linux 2207 ms 2359 ms 0.94
eda-sourceToZip-linux 1828 ms 1864 ms 0.98
eda-mdapiToSource-linux 2939 ms 2949 ms 1.00
lotsOfClasses-componentSetCreate-linux 450 ms 421 ms 1.07
lotsOfClasses-sourceToMdapi-linux 3639 ms 3712 ms 0.98
lotsOfClasses-sourceToZip-linux 3142 ms 3098 ms 1.01
lotsOfClasses-mdapiToSource-linux 3559 ms 3541 ms 1.01
lotsOfClassesOneDir-componentSetCreate-linux 753 ms 758 ms 0.99
lotsOfClassesOneDir-sourceToMdapi-linux 6469 ms 6432 ms 1.01
lotsOfClassesOneDir-sourceToZip-linux 5596 ms 5574 ms 1.00
lotsOfClassesOneDir-mdapiToSource-linux 6463 ms 6448 ms 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@svc-cli-bot
Copy link
Collaborator

Choose a reason for hiding this comment

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

Benchmark

Benchmark suite Current: 36c5e1c Previous: 12b5904 Ratio
eda-componentSetCreate-win32 703 ms 659 ms 1.07
eda-sourceToMdapi-win32 4775 ms 4428 ms 1.08
eda-sourceToZip-win32 3253 ms 3005 ms 1.08
eda-mdapiToSource-win32 6207 ms 5583 ms 1.11
lotsOfClasses-componentSetCreate-win32 1288 ms 1195 ms 1.08
lotsOfClasses-sourceToMdapi-win32 8241 ms 7762 ms 1.06
lotsOfClasses-sourceToZip-win32 5498 ms 5046 ms 1.09
lotsOfClasses-mdapiToSource-win32 8592 ms 7882 ms 1.09
lotsOfClassesOneDir-componentSetCreate-win32 2408 ms 2147 ms 1.12
lotsOfClassesOneDir-sourceToMdapi-win32 15385 ms 13901 ms 1.11
lotsOfClassesOneDir-sourceToZip-win32 10096 ms 9365 ms 1.08
lotsOfClassesOneDir-mdapiToSource-win32 14276 ms 14085 ms 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.