sf-decomposer
Version:
Break down large Salesforce metadata files into smaller, more manageable files for version control and then recreate deployment-compatible files.
114 lines • 5.57 kB
JavaScript
;
/* eslint-disable no-await-in-loop */
import { resolve, relative, join } from 'node:path';
import { readdir, stat, rm, rename } from 'node:fs/promises';
import { DisassembleXMLFileHandler, setLogLevel } from 'xml-disassembler';
import { CUSTOM_LABELS_FILE, WORKFLOW_SUFFIX_MAPPING } from '../../helpers/constants.js';
import { moveFiles } from '../core/moveFiles.js';
import { handleNestedLoyaltyProgramSetupDecomposition } from './lps/loyaltyProgramSetup.js';
import { handleNestedPermissionSetDecomposition } from './perm-set/permSets.js';
export async function decomposeFileHandler(metaAttributes, prepurge, postpurge, debug, format, ignorePath, strategy, decomposeNestedPerms) {
const { metadataPaths, metaSuffix, strictDirectoryName, folderType, uniqueIdElements } = metaAttributes;
if (debug)
setLogLevel('debug');
for (const metadataPath of metadataPaths) {
if (strictDirectoryName || folderType) {
await subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
}
else if (metaSuffix === 'labels') {
// do not use the prePurge flag in the xml-disassembler package for labels due to file moving
if (prepurge)
await prePurgeLabels(metadataPath);
const absoluteLabelFilePath = resolve(metadataPath, CUSTOM_LABELS_FILE);
const relativeLabelFilePath = relative(process.cwd(), absoluteLabelFilePath);
await disassembleHandler(relativeLabelFilePath, uniqueIdElements, false, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
// move labels from the directory they are created in
await moveAndRenameLabels(metadataPath);
}
else {
await disassembleHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
}
if (metaSuffix === 'workflow') {
await renameWorkflows(metadataPath);
}
}
}
async function disassembleHandler(filePath, uniqueIdElements, prePurge, postPurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms) {
const handler = new DisassembleXMLFileHandler();
let decomposeFormat;
let decomposePostPurge;
const decomposePermSets = decomposeNestedPerms && metaSuffix === 'permissionset' && strategy === 'grouped-by-tag';
const decomposeLoyalyProgram = metaSuffix === 'loyaltyProgramSetup' && strategy === 'unique-id';
if (decomposePermSets || decomposeLoyalyProgram) {
decomposeFormat = 'xml';
decomposePostPurge = false;
}
else {
decomposeFormat = format;
decomposePostPurge = postPurge;
}
await handler.disassemble({
filePath,
uniqueIdElements,
prePurge,
postPurge: decomposePostPurge,
ignorePath,
format: decomposeFormat,
strategy,
});
// Dispatch recursive decomposition based on type
if (decomposePermSets) {
await handleNestedPermissionSetDecomposition(filePath, uniqueIdElements, handler, format);
}
if (decomposeLoyalyProgram) {
await handleNestedLoyaltyProgramSetupDecomposition(filePath, handler, format);
}
}
async function prePurgeLabels(metadataPath) {
const subFiles = await readdir(metadataPath);
for (const subFile of subFiles) {
const subfilePath = join(metadataPath, subFile);
if ((await stat(subfilePath)).isFile() && subFile !== CUSTOM_LABELS_FILE) {
await rm(subfilePath, { recursive: true });
}
}
}
async function moveAndRenameLabels(metadataPath) {
const sourceDirectory = join(metadataPath, 'CustomLabels', 'labels');
const destinationDirectory = metadataPath;
const labelFiles = await readdir(sourceDirectory);
for (const file of labelFiles) {
if (file.includes('.labels-meta')) {
const oldFilePath = join(sourceDirectory, file);
const newFileName = file.replace('.labels-meta', '.label-meta');
const newFilePath = join(destinationDirectory, newFileName);
await rename(oldFilePath, newFilePath);
}
}
await moveFiles(sourceDirectory, destinationDirectory, () => true);
await rm(join(metadataPath, 'CustomLabels'), { recursive: true });
}
async function subDirectoryHandler(metadataPath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms) {
const subFiles = await readdir(metadataPath);
for (const subFile of subFiles) {
const subFilePath = join(metadataPath, subFile);
if ((await stat(subFilePath)).isDirectory()) {
await disassembleHandler(subFilePath, uniqueIdElements, prepurge, postpurge, format, ignorePath, strategy, metaSuffix, decomposeNestedPerms);
}
}
}
async function renameWorkflows(directory) {
const files = await readdir(directory, { recursive: true });
for (const file of files) {
// Check if the file matches any suffix in WORKFLOW_SUFFIX_MAPPING
for (const [suffix, newSuffix] of Object.entries(WORKFLOW_SUFFIX_MAPPING)) {
if (file.includes(suffix)) {
const oldFilePath = join(directory, file);
const newFilePath = join(directory, file.replace(suffix, newSuffix));
await rename(oldFilePath, newFilePath);
break;
}
}
}
}
//# sourceMappingURL=decomposeFileHandler.js.map