sf-decomposer
Version:
Decompose Salesforce metadata into granular, VCS-friendly files; recompose for deployment.
81 lines • 4.2 kB
JavaScript
;
import { RegistryAccess } from '@salesforce/source-deploy-retrieve';
import { DEFAULT_UNIQUE_ID_ELEMENTS, UNSUPPORTED_ADAPTERS } from '../helpers/constants.js';
import { getPackageDirectories } from './getPackageDirectories.js';
import { getUniqueIdElements } from './getUniqueIdElements.js';
// Singleton instance for RegistryAccess to avoid repeated instantiation
let registryAccessInstance = null;
// Lazy-built reverse map: suffix → child MetadataType (for child types whose suffix differs from xmlName)
let childSuffixMap = null;
function getRegistryAccessInstance() {
if (!registryAccessInstance) {
registryAccessInstance = new RegistryAccess();
}
return registryAccessInstance;
}
function getChildSuffixMap(registryAccess) {
if (!childSuffixMap) {
childSuffixMap = new Map();
const reg = registryAccess.registry;
for (const childXmlNameLower of Object.keys(reg.childTypes)) {
const parentType = registryAccess.getParentType(childXmlNameLower);
const childEntry = parentType?.children?.types[childXmlNameLower];
/* v8 ignore next -- defensive guard; SDR registry always provides a suffix for child types */
if (childEntry?.suffix) {
childSuffixMap.set(childEntry.suffix, childEntry);
}
}
}
return childSuffixMap;
}
/**
* Resolves and validates the SDR registry entry for a metadata suffix (rejects `object`, unknown
* suffixes, and unsupported adapter strategies). Synchronous and side-effect free, so callers can
* use it to learn a type's `directoryName` ahead of time — e.g. to build a shared
* `buildPackageDirectoryIndex` covering every requested type in one filesystem walk — without
* duplicating this lookup logic.
*/
export function resolveMetadataTypeEntry(metaSuffix) {
if (metaSuffix === 'object') {
throw Error('Custom Objects are not supported by this plugin.');
}
const registryAccess = getRegistryAccessInstance();
let metadataTypeEntry = registryAccess.getTypeBySuffix(metaSuffix);
if (metadataTypeEntry === undefined) {
// Child types are not in the top-level suffix index. children.types is keyed by lowercased
// xmlName, not suffix — so 'recordType' works (suffix === xmlName lowercased) but 'field'
// (xmlName: CustomField) does not. Fall back to the pre-built suffix map.
metadataTypeEntry = getChildSuffixMap(registryAccess).get(metaSuffix);
}
if (metadataTypeEntry === undefined)
throw Error(`Metadata type not found for the given suffix: ${metaSuffix}.`);
if (metadataTypeEntry.strategies?.adapter && UNSUPPORTED_ADAPTERS.includes(metadataTypeEntry.strategies.adapter)) {
throw Error(`Metadata types with ${metadataTypeEntry.strategies.adapter} strategies are not supported by this plugin.`);
}
return metadataTypeEntry;
}
export async function getRegistryValuesBySuffix(metaSuffix, command, ignoreDirs, repoRootOverride, uniqueIdOverride, pathIndex) {
const metadataTypeEntry = resolveMetadataTypeEntry(metaSuffix);
let uniqueIdElements;
if (command === 'decompose')
uniqueIdElements = uniqueIdOverride ?? getUniqueIdElements(metaSuffix);
const { metadataPaths, ignorePath } = pathIndex
? {
metadataPaths: pathIndex.index.get(`${metadataTypeEntry.directoryName}`) ?? [],
ignorePath: pathIndex.ignorePath,
}
: await getPackageDirectories(`${metadataTypeEntry.directoryName}`, ignoreDirs, repoRootOverride);
if (metadataPaths.length === 0)
throw Error(`No directories named ${metadataTypeEntry.directoryName} were found in any package directory.`);
const metaAttributes = {
metaSuffix: metadataTypeEntry.suffix,
strictDirectoryName: metadataTypeEntry.strictDirectoryName,
folderType: metadataTypeEntry.folderType,
metadataPaths,
uniqueIdElements: uniqueIdElements
? `${DEFAULT_UNIQUE_ID_ELEMENTS},${uniqueIdElements}`
: DEFAULT_UNIQUE_ID_ELEMENTS,
};
return { metaAttributes, ignorePath };
}
//# sourceMappingURL=getRegistryValuesBySuffix.js.map