UNPKG

sfdx-hardis

Version:

Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards

228 lines • 11.2 kB
import { XMLBuilder, XMLParser } from "fast-xml-parser"; import { buildGenericMarkdownTable, prettifyFieldName } from "../utils/flowVisualiser/nodeFormatUtils.js"; import { DocBuilderRoot } from "./docBuilderRoot.js"; /* jscpd:ignore-start */ export class DocBuilderProfile extends DocBuilderRoot { docType = "Profile"; promptKey = "PROMPT_DESCRIBE_PROFILE"; placeholder = "<!-- Profile description -->"; xmlRootKey = "Profile"; docsSection = "profiles"; static buildIndexTable(prefix, profileDescriptions, filterObject = null) { const filteredProfiles = filterObject ? profileDescriptions.filter(profile => profile.impactedObjects.includes(filterObject)) : profileDescriptions; if (filteredProfiles.length === 0) { return []; } const lines = []; lines.push(...[ filterObject ? "## Related Profiles" : "## Profiles", "", "| Profile | User License |", "| :---- | :--: | " ]); for (const profile of filteredProfiles) { const profileNameCell = `[${profile.name}](${prefix}${encodeURIComponent(profile.name)}.md)`; lines.push(...[ `| ${profileNameCell} | ${profile.userLicense} |` ]); } lines.push(""); return lines; } async buildInitialMarkdownLines() { return [ `## ${this.metadataName}`, '', '<div id="jstree-container"></div>', '', buildGenericMarkdownTable(this.parsedXmlObject, ["userLicense", "custom"], "## Profile attributes", []), '', '<!-- Profile description -->', '', ]; } stripXmlForAi() { const xmlObj = new XMLParser().parse(this.metadataXml); // Remove class access: not relevant for prompt if (xmlObj?.Profile?.classAccesses) { delete xmlObj.Profile.classAccesses; } // Remove fieldPermissions: not relevant for prompt if (xmlObj?.Profile?.fieldPermissions) { delete xmlObj.Profile.fieldPermissions; } // Remove flowAccesses: not relevant for prompt if (xmlObj?.Profile?.flowAccesses) { delete xmlObj.Profile.flowAccesses; } // Remove layoutAssignments: not relevant for prompt if (xmlObj?.Profile?.layoutAssignments) { delete xmlObj.Profile.layoutAssignments; } // Remove pageAccesses: not relevant for prompt if (xmlObj?.Profile?.pageAccesses) { delete xmlObj.Profile.pageAccesses; } // Keep only visible applications if (xmlObj?.Profile?.applicationVisibilities) { if (!Array.isArray(xmlObj.Profile.applicationVisibilities)) { xmlObj.Profile.applicationVisibilities = [xmlObj.Profile.applicationVisibilities]; } xmlObj.Profile.applicationVisibilities = xmlObj.Profile.applicationVisibilities.filter(applicationVisibility => applicationVisibility.visible === true); } // Keep only visible recordTypes if (xmlObj?.Profile?.recordTypeVisibilities) { if (!Array.isArray(xmlObj.Profile.recordTypeVisibilities)) { xmlObj.Profile.recordTypeVisibilities = [xmlObj.Profile.recordTypeVisibilities]; } xmlObj.Profile.recordTypeVisibilities = xmlObj.Profile.recordTypeVisibilities.filter(rt => rt.visible === true); } // Keep only visible tabs if (xmlObj?.Profile?.tabVisibilities) { if (!Array.isArray(xmlObj.Profile.tabVisibilities)) { xmlObj.Profile.tabVisibilities = [xmlObj.Profile.tabVisibilities]; } xmlObj.Profile.tabVisibilities = xmlObj.Profile.tabVisibilities.filter(tab => tab.visibility === 'Hidden'); } const xmlStripped = new XMLBuilder().build(xmlObj); return xmlStripped; } // Generate json for display with jsTree npm library async generateJsonTree() { const xmlObj = new XMLParser().parse(this.metadataXml); const treeElements = []; for (const profileRootAttribute of Object.keys(xmlObj?.Profile || {})) { if (["custom", "userLicense"].includes(profileRootAttribute)) { continue; } let attributeValue = xmlObj.Profile[profileRootAttribute]; if (!Array.isArray(attributeValue)) { attributeValue = [attributeValue]; } const attributeTreeRoot = { text: prettifyFieldName(profileRootAttribute), icon: "fa-solid fa-folder icon-blue", a_attr: { href: null }, children: [], }; if (profileRootAttribute === "fieldPermissions") { // Sort custom fields by object name this.buildObjectFieldsTree(attributeValue, attributeTreeRoot); } else { for (const element of attributeValue) { if (!this.isAccessibleElement(element)) { continue; } const subElement = this.getSubElement(element); attributeTreeRoot.children.push(subElement); } attributeTreeRoot.text = attributeTreeRoot.text + " (" + attributeTreeRoot.children.length + ")"; } if (attributeTreeRoot.children.length > 0) { treeElements.push(attributeTreeRoot); } } return treeElements; } buildObjectFieldsTree(attributeValue, attributeTreeRoot) { const elementsByObject = []; for (const element of attributeValue) { const objectName = element.field.split('.')[0]; if (!elementsByObject[objectName]) { elementsByObject[objectName] = []; } elementsByObject[objectName].push(element); } // Create object nodes and fields as children let totalFields = 0; for (const objectName of Object.keys(elementsByObject)) { const objectNode = { text: objectName + " (" + elementsByObject[objectName].length + ")", icon: "fa-solid fa-folder icon-blue", a_attr: { href: null }, children: [], }; for (const element of elementsByObject[objectName]) { if (!this.isAccessibleElement(element)) { continue; } const subElement = this.getSubElement(element); objectNode.children.push(subElement); } if (objectNode.children.length > 0) { attributeTreeRoot.children.push(objectNode); totalFields += objectNode.children.length; } } attributeTreeRoot.text = attributeTreeRoot.text + " (" + totalFields + ")"; } isAccessibleElement(element) { if (element.visible === false) { return false; } if (element.readable === false) { return false; } if (element.allowRead === false) { return false; } if (element.enabled === false) { return false; } return true; } getSubElement(element) { const subElement = { text: element.name || element.apexClass || element.flow || element.apexPage || element.object || element.tab || element.application || element.field || element.layout || element.recordType || element.externalDataSource || element.startAddress || element.dataspaceScope || "ERROR: " + JSON.stringify(element), icon: // Common properties element.default === true ? "fa-solid fa-star icon-success" : element.visible === true ? "fa-solid fa-eye icon-success" : element.visible === false ? "fa-solid fa-eye-slash icon-error" : element.enabled === true ? "fa-solid fa-circle-check icon-success" : element.enabled === false ? "fa-solid fa-circle-xmark icon-error" : // Custom fields element.editable === true ? "fa-solid fa-square-pen icon-success" : element.readable === true ? "fa-solid fa-eye icon-success" : element.readable === false ? "fa-solid fa-eye-slash icon-error" : // Custom objects element.modifyAllRecords === true ? "fa-solid fa-web-awesome icon-success" : element.viewAllRecords === true && element.allowEdit === false ? "fa-solid fa-magnifying-glass icon-success" : element.allowEdit === true ? "fa-solid fa-square-pen icon-success" : element.allowRead === true ? "fa-solid fa-eye icon-success" : element.allowRead === false ? "fa-solid fa-eye-slash icon-error" : // Tabs ["DefaultOn", "Visible"].includes(element.visibility) ? "fa-solid fa-eye icon-success" : element.visibility === "DefaultOff" ? "fa-solid fa-circle-notch icon-warning" : element.visibility === "Hidden" ? "fa-solid fa-eye-slash icon-error" : "fa-solid fa-file", a_attr: { href: null }, children: [], }; subElement.children = Object.keys(element).map((key) => { const icon = (element[key] === true) ? "fa-solid fa-circle-check icon-success" : (element[key] === false) ? "fa-solid fa-circle-xmark icon-error" : (["DefaultOn", "Visible"].includes(element[key])) ? "fa-solid fa-eye icon-success" : (element[key] === "Hidden") ? "fa-solid fa-eye-slash icon-error" : (element[key] === "DefaultOff") ? "fa-solid fa-circle-notch icon-warning" : ""; return { text: prettifyFieldName(key) + ": " + element[key], icon: icon, a_attr: { href: null }, }; }); // Sort subElement.children to put text as first element subElement.children.sort((a, b) => { if (a.text.endsWith(subElement.text)) return -1; if (b.text.endsWith(subElement.text)) return 1; return 0; }); return subElement; } } /* jscpd:ignore-end */ //# sourceMappingURL=docBuilderProfile.js.map