UNPKG

@cparra/apexdocs

Version:

Library with CLI capabilities to generate documentation for Salesforce Apex classes.

1,432 lines (1,388 loc) 197 kB
'use strict'; var _function = require('fp-ts/function'); var TE = require('fp-ts/TaskEither'); var E = require('fp-ts/Either'); var yaml = require('js-yaml'); var path = require('path'); var T = require('fp-ts/Task'); var A = require('fp-ts/lib/Array'); var apexReflection = require('@cparra/apex-reflection'); var O = require('fp-ts/Option'); var fastXmlParser = require('fast-xml-parser'); var Handlebars = require('handlebars'); var boolean = require('fp-ts/boolean'); var A$1 = require('fp-ts/Array'); var fs = require('fs'); var TE$1 = require('fp-ts/lib/TaskEither'); var minimatch = require('minimatch'); var sourceDeployRetrieve = require('@salesforce/source-deploy-retrieve'); var chalk = require('chalk'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var TE__namespace = /*#__PURE__*/_interopNamespaceDefault(TE); var E__namespace = /*#__PURE__*/_interopNamespaceDefault(E); var yaml__namespace = /*#__PURE__*/_interopNamespaceDefault(yaml); var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); var T__namespace = /*#__PURE__*/_interopNamespaceDefault(T); var A__namespace = /*#__PURE__*/_interopNamespaceDefault(A); var O__namespace = /*#__PURE__*/_interopNamespaceDefault(O); var A__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(A$1); var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs); var TE__namespace$1 = /*#__PURE__*/_interopNamespaceDefault(TE$1); function apply(fn, ...front) { return (...tailArgs) => fn(...front, ...tailArgs); } const defaultTranslations = { changelog: { title: "Changelog", newClasses: { heading: "New Classes", description: "These classes are new." }, newInterfaces: { heading: "New Interfaces", description: "These interfaces are new." }, newEnums: { heading: "New Enums", description: "These enums are new." }, newCustomObjects: { heading: "New Custom Objects", description: "These custom objects are new." }, newTriggers: { heading: "New Triggers", description: "These triggers are new." }, removedTypes: { heading: "Removed Types", description: "These types have been removed." }, removedCustomObjects: { heading: "Removed Custom Objects", description: "These custom objects have been removed." }, removedTriggers: { heading: "Removed Triggers", description: "These triggers have been removed." }, newOrModifiedMembers: { heading: "New or Modified Members in Existing Types", description: "These members have been added or modified." }, newOrRemovedCustomFields: { heading: "New or Removed Fields to Custom Objects or Standard Objects", description: "These custom fields have been added or removed." }, newOrRemovedCustomMetadataTypeRecords: { heading: "New or Removed Custom Metadata Type Records", description: "These custom metadata type records have been added or removed." }, memberModifications: { newEnumValue: "New Enum Value", removedEnumValue: "Removed Enum Value", newMethod: "New Method", removedMethod: "Removed Method", newProperty: "New Property", removedProperty: "Removed Property", newField: "New Field", removedField: "Removed Field", newType: "New Type", removedType: "Removed Type", newCustomMetadataRecord: "New Custom Metadata Record", removedCustomMetadataRecord: "Removed Custom Metadata Record", newTrigger: "New Trigger", removedTrigger: "Removed Trigger" } }, markdown: { sections: { methods: "Methods", properties: "Properties", fields: "Fields", constructors: "Constructors", values: "Values", classes: "Classes", enums: "Enums", interfaces: "Interfaces", namespace: "Namespace", records: "Records", publishBehavior: "Publish Behavior" }, details: { type: "Type", signature: "Signature", group: "Group", author: "Author", date: "Date", see: "See", possibleValues: "Possible values are", parameters: "Parameters", throws: "Throws", returnType: "Return Type", apiName: "API Name", required: "Required", inlineHelpText: "Inline Help Text", complianceGroup: "Compliance Group", securityClassification: "Security Classification", protected: "Protected" }, typeSuffixes: { class: "Class", interface: "Interface", enum: "Enum", trigger: "Trigger" }, triggerEvents: { beforeInsert: "Before Insert", beforeUpdate: "Before Update", beforeDelete: "Before Delete", afterInsert: "After Insert", afterUpdate: "After Update", afterDelete: "After Delete", afterUndelete: "After Undelete" }, publishBehaviors: { publishImmediately: "Publish Immediately", publishAfterCommit: "Publish After Commit" }, inheritance: { inheritance: "Inheritance", implements: "Implements" } } }; var __defProp$q = Object.defineProperty; var __getOwnPropSymbols$q = Object.getOwnPropertySymbols; var __hasOwnProp$q = Object.prototype.hasOwnProperty; var __propIsEnum$q = Object.prototype.propertyIsEnumerable; var __defNormalProp$q = (obj, key, value) => key in obj ? __defProp$q(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$q = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$q.call(b, prop)) __defNormalProp$q(a, prop, b[prop]); if (__getOwnPropSymbols$q) for (var prop of __getOwnPropSymbols$q(b)) { if (__propIsEnum$q.call(b, prop)) __defNormalProp$q(a, prop, b[prop]); } return a; }; function mergeTranslations(userTranslations) { if (!userTranslations) { return defaultTranslations; } return JSON.parse( JSON.stringify(Object.assign({}, defaultTranslations, deepMerge(defaultTranslations, userTranslations))) ); } function isObjectWithStringKeys(value) { return value !== null && typeof value === "object" && !Array.isArray(value); } function deepMerge(target, source) { const result = __spreadValues$q({}, target); for (const key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { const sourceValue = source[key]; const targetValue = result[key]; if (isObjectWithStringKeys(sourceValue) && isObjectWithStringKeys(targetValue)) { result[key] = deepMerge(targetValue, sourceValue); } else if (sourceValue !== void 0) { result[key] = sourceValue; } } } return result; } function defaultGetEmailByReference(email) { return { __type: "link", title: email, url: `mailto:${email}` }; } function replaceInlineReferences(text, linkReplacer, emailReplacer = defaultGetEmailByReference) { const inlineLinks = apply(replaceInlineLinks, linkReplacer); const inlineEmails = apply(replaceInlineEmails, emailReplacer); return _function.pipe(inlineCode$1([text]), inlineLinks, inlineEmails); } function inlineCode$1(renderableContents) { return renderableContents.flatMap((renderableContent) => inlineCodeContent(renderableContent)); } function inlineCodeContent(renderableContent) { if (typeof renderableContent !== "string") { return [renderableContent]; } function inlineCodeLink(text2) { return { __type: "inline-code", content: text2 }; } const text = renderableContent; const codeFormatRegEx = "`([^`]*)`"; const matches = match(codeFormatRegEx, text); return createRenderableContents(matches, text, inlineCodeLink); } function replaceInlineLinks(getLinkByTypeName, renderableContents) { return renderableContents.flatMap((renderableContent) => inlineLinkContent(renderableContent, getLinkByTypeName)); } function inlineLinkContent(renderableContent, getLinkByTypeName) { if (typeof renderableContent !== "string") { return [renderableContent]; } const text = renderableContent; const linkFormatRegEx = "{@link (.*?)}|<<([^>]+)>>"; const matches = match(linkFormatRegEx, text); return createRenderableContents(matches, text, getLinkByTypeName); } function replaceInlineEmails(getLinkByTypeName, renderableContents) { return renderableContents.flatMap((renderableContent) => inlineEmailContent(renderableContent, getLinkByTypeName)); } function inlineEmailContent(renderableContent, getLinkByTypeName) { if (typeof renderableContent !== "string") { return [renderableContent]; } const text = renderableContent; const linkFormatRegEx = "{@email (.*?)}"; const matches = match(linkFormatRegEx, text); return createRenderableContents(matches, text, getLinkByTypeName); } function match(regex, text) { const expression = new RegExp(regex, "gi"); let match2; const matches = []; do { match2 = expression.exec(text); if (match2) { matches.push(match2); } } while (match2); return matches; } function createRenderableContents(matches, text, linker) { if (matches.length === 0) { return [text]; } const result = []; let lastIndex = 0; for (const match2 of matches) { const index = match2.index; const length = match2[0].length; const capturedGroup = match2.slice(1).find((group) => group); if (!capturedGroup) { continue; } result.push(text.slice(lastIndex, index)); result.push(linker(capturedGroup)); lastIndex = index + length; } if (lastIndex < text.length) { result.push(text.slice(lastIndex)); } return result; } function isEmptyLine(content) { return Object.keys(content).includes("__type") && content.__type === "empty-line"; } function isCodeBlock(content) { return Object.keys(content).includes("__type") && content.__type === "code-block"; } function isInlineCode(content) { return Object.keys(content).includes("__type") && content.__type === "inline-code"; } var __defProp$p = Object.defineProperty; var __defProps$p = Object.defineProperties; var __getOwnPropDescs$p = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$p = Object.getOwnPropertySymbols; var __hasOwnProp$p = Object.prototype.hasOwnProperty; var __propIsEnum$p = Object.prototype.propertyIsEnumerable; var __defNormalProp$p = (obj, key, value) => key in obj ? __defProp$p(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$p = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$p.call(b, prop)) __defNormalProp$p(a, prop, b[prop]); if (__getOwnPropSymbols$p) for (var prop of __getOwnPropSymbols$p(b)) { if (__propIsEnum$p.call(b, prop)) __defNormalProp$p(a, prop, b[prop]); } return a; }; var __spreadProps$p = (a, b) => __defProps$p(a, __getOwnPropDescs$p(b)); function adaptDescribable(describable, linkGenerator) { return { description: describableToRenderableContent(describable, linkGenerator) }; } function describableToRenderableContent(describable, linkGenerator) { if (!describable) { return; } let content = []; for (let i = 0; i < describable.length; i++) { const line = describable[i]; const codeBlockMatch = line.match(/^```([a-zA-Z]*)$/); if (codeBlockMatch) { const language = codeBlockMatch[1] || "apex"; const codeBlockLines = []; i++; while (i < describable.length) { const currentLine = describable[i]; if (currentLine.trim() === "```") { break; } codeBlockLines.push(currentLine); i++; } content = [ ...content, { __type: "code-block", language, content: codeBlockLines }, { __type: "empty-line" } ]; continue; } content = [ ...content, ...replaceInlineReferences(line, linkGenerator), { __type: "empty-line" } ]; } return content.filter((line, index, lines) => !(isEmptyLine(line) && index === lines.length - 1)); } function adaptDocumentable(documentable, linkGenerator, subHeadingLevel) { var _a, _b, _c; function extractCustomTags(type) { var _a2, _b2; const baseTags = ["description", "group", "author", "date", "see", "example", "throws", "exception"]; return (_b2 = (_a2 = type.docComment) == null ? void 0 : _a2.annotations.filter((currentAnnotation) => !baseTags.includes(currentAnnotation.name.toLowerCase())).map((currentAnnotation) => __spreadProps$p(__spreadValues$p({}, adaptDescribable(currentAnnotation.bodyLines, linkGenerator)), { name: currentAnnotation.name }))) != null ? _b2 : []; } function extractAnnotationBody(type, annotationName) { var _a2, _b2; return (_b2 = (_a2 = type.docComment) == null ? void 0 : _a2.annotations.find( (currentAnnotation) => currentAnnotation.name.toLowerCase() === annotationName )) == null ? void 0 : _b2.body; } function extractSeeAnnotations(type) { var _a2, _b2; return (_b2 = (_a2 = type.docComment) == null ? void 0 : _a2.annotations.filter((currentAnnotation) => currentAnnotation.name.toLowerCase() === "see").map((currentAnnotation) => currentAnnotation.body)) != null ? _b2 : []; } return __spreadProps$p(__spreadValues$p({}, adaptDescribable((_a = documentable.docComment) == null ? void 0 : _a.descriptionLines, linkGenerator)), { annotations: documentable.annotations.map((annotation) => annotation.type.toUpperCase()), customTags: extractCustomTags(documentable), example: { headingLevel: subHeadingLevel, heading: "Example", value: describableToRenderableContent((_c = (_b = documentable.docComment) == null ? void 0 : _b.exampleAnnotation) == null ? void 0 : _c.bodyLines, linkGenerator) }, group: extractAnnotationBody(documentable, "group"), author: extractAnnotationBody(documentable, "author"), date: extractAnnotationBody(documentable, "date"), sees: extractSeeAnnotations(documentable).map(linkGenerator) }); } var __defProp$o = Object.defineProperty; var __defProps$o = Object.defineProperties; var __getOwnPropDescs$o = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$o = Object.getOwnPropertySymbols; var __hasOwnProp$o = Object.prototype.hasOwnProperty; var __propIsEnum$o = Object.prototype.propertyIsEnumerable; var __defNormalProp$o = (obj, key, value) => key in obj ? __defProp$o(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$o = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$o.call(b, prop)) __defNormalProp$o(a, prop, b[prop]); if (__getOwnPropSymbols$o) for (var prop of __getOwnPropSymbols$o(b)) { if (__propIsEnum$o.call(b, prop)) __defNormalProp$o(a, prop, b[prop]); } return a; }; var __spreadProps$o = (a, b) => __defProps$o(a, __getOwnPropDescs$o(b)); function adaptMethod(method, linkGenerator, baseHeadingLevel, translations) { var _a, _b, _c; function buildTitle(method2) { const { name, parameters } = method2; const parametersString = parameters.map((param) => param.name).join(", "); return `${name}(${parametersString})`; } function buildSignature(method2) { const { access_modifier, typeReference, name, memberModifiers } = method2; const parameters = method2.parameters.map((param) => `${param.typeReference.rawDeclaration} ${param.name}`).join(", "); const members = memberModifiers.length > 0 ? `${memberModifiers.join(" ")} ` : ""; return { __type: "code-block", language: "apex", content: [`${access_modifier} ${members}${typeReference.rawDeclaration} ${name}(${parameters})`] }; } return { headingLevel: baseHeadingLevel, doc: adaptDocumentable(method, linkGenerator, baseHeadingLevel + 1), heading: buildTitle(method), signature: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.signature, value: buildSignature(method) }, returnType: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.returnType, value: __spreadProps$o(__spreadValues$o({}, adaptDescribable((_b = (_a = method.docComment) == null ? void 0 : _a.returnAnnotation) == null ? void 0 : _b.bodyLines, linkGenerator)), { type: linkGenerator(method.typeReference.rawDeclaration) }) }, throws: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.throws, value: (_c = method.docComment) == null ? void 0 : _c.throwsAnnotations.map((thrown) => mapThrows(thrown, linkGenerator)) }, parameters: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.parameters, value: method.parameters.map((param) => mapParameters(method, param, linkGenerator)) }, inherited: method.inherited }; } function adaptConstructor(typeName, constructor, linkGenerator, baseHeadingLevel, translations) { var _a; function buildTitle(name, constructor2) { const { parameters } = constructor2; const parametersString = parameters.map((param) => param.name).join(", "); return `${name}(${parametersString})`; } function buildSignature(name, constructor2) { const { access_modifier } = constructor2; const parameters = constructor2.parameters.map((param) => `${param.typeReference.rawDeclaration} ${param.name}`).join(", "); return { __type: "code-block", language: "apex", content: [`${access_modifier} ${name}(${parameters})`] }; } return { doc: adaptDocumentable(constructor, linkGenerator, baseHeadingLevel + 1), headingLevel: baseHeadingLevel, heading: buildTitle(typeName, constructor), signature: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.signature, value: buildSignature(typeName, constructor) }, parameters: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.parameters, value: constructor.parameters.map((param) => mapParameters(constructor, param, linkGenerator)) }, throws: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.throws, value: (_a = constructor.docComment) == null ? void 0 : _a.throwsAnnotations.map((thrown) => mapThrows(thrown, linkGenerator)) } }; } function mapParameters(documentable, param, linkGenerator) { var _a; const paramAnnotation = (_a = documentable.docComment) == null ? void 0 : _a.paramAnnotations.find( (pa) => pa.paramName.toLowerCase() === param.name.toLowerCase() ); return __spreadProps$o(__spreadValues$o({}, adaptDescribable(paramAnnotation == null ? void 0 : paramAnnotation.bodyLines, linkGenerator)), { name: param.name, type: linkGenerator(param.typeReference.rawDeclaration) }); } function mapThrows(thrown, linkGenerator) { return __spreadProps$o(__spreadValues$o({}, adaptDescribable(thrown.bodyLines, linkGenerator)), { type: linkGenerator(thrown.exceptionName) }); } function adaptFieldOrProperty(field, linkGenerator, baseHeadingLevel, translations) { function buildSignature() { const { access_modifier, name } = field; const memberModifiers = field.memberModifiers.join(" "); const codeContents = `${access_modifier} ${memberModifiers} ${name}`.replace(/ {2}/g, " "); return { __type: "code-block", language: "apex", content: [codeContents] }; } return { headingLevel: baseHeadingLevel, doc: adaptDocumentable(field, linkGenerator, baseHeadingLevel + 1), heading: field.name, type: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.type, value: linkGenerator(field.typeReference.rawDeclaration) }, inherited: field.inherited, accessModifier: field.access_modifier, signature: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.details.signature, value: buildSignature() } }; } function skip() { return { _tag: "Skip" }; } function isSkip(value) { return Object.prototype.hasOwnProperty.call(value, "_tag") && value._tag === "Skip"; } function isObjectType(type) { return type.type_name === "customobject"; } function isApexType(type) { return !isObjectType(type) && !isTriggerType(type); } function isTriggerType(type) { return type.type_name === "trigger"; } function isInSource(source) { return "filePath" in source; } function getTypeGroup(type, config) { function getGroup(type2, config2) { var _a, _b; const groupAnnotation = (_a = type2.docComment) == null ? void 0 : _a.annotations.find( (annotation) => annotation.name.toLowerCase() === "group" ); return (_b = groupAnnotation == null ? void 0 : groupAnnotation.body) != null ? _b : config2.defaultGroupName; } switch (type.type_name) { case "customobject": return config.customObjectsGroupName; case "trigger": return config.triggersGroupName; default: return getGroup(type, config); } } function passThroughHook(value) { return value; } function toFrontmatterString(frontmatter) { if (typeof frontmatter === "string") { return frontmatter; } if (!frontmatter) { return ""; } const yamlString = yaml.dump(frontmatter); return `--- ${yamlString}--- `; } var __defProp$n = Object.defineProperty; var __defProps$n = Object.defineProperties; var __getOwnPropDescs$n = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$n = Object.getOwnPropertySymbols; var __hasOwnProp$n = Object.prototype.hasOwnProperty; var __propIsEnum$n = Object.prototype.propertyIsEnumerable; var __defNormalProp$n = (obj, key, value) => key in obj ? __defProp$n(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$n = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$n.call(b, prop)) __defNormalProp$n(a, prop, b[prop]); if (__getOwnPropSymbols$n) for (var prop of __getOwnPropSymbols$n(b)) { if (__propIsEnum$n.call(b, prop)) __defNormalProp$n(a, prop, b[prop]); } return a; }; var __spreadProps$n = (a, b) => __defProps$n(a, __getOwnPropDescs$n(b)); function typeToRenderable$1(parsedFile, linkGenerator, config, translations) { function getRenderable() { const { type } = parsedFile; switch (type.type_name) { case "enum": return enumTypeToEnumSource(type, linkGenerator, 1, translations); case "interface": return interfaceTypeToInterfaceSource(type, linkGenerator, 1, translations); case "class": return classTypeToClassSource(type, linkGenerator, 1, translations); case "trigger": return triggerMetadataToRenderable(type, linkGenerator, 1, translations); case "customobject": return objectMetadataToRenderable(type, config, translations); } } return __spreadProps$n(__spreadValues$n({}, getRenderable()), { filePath: isInSource(parsedFile.source) ? parsedFile.source.filePath : void 0, namespace: config.namespace }); } function baseTypeAdapter(type, linkGenerator, baseHeadingLevel, translations) { function getHeading(type2) { const suffixMap = { class: translations.markdown.typeSuffixes.class, interface: translations.markdown.typeSuffixes.interface, enum: translations.markdown.typeSuffixes.enum }; return `${type2.name} ${suffixMap[type2.type_name]}`; } return { headingLevel: baseHeadingLevel, heading: getHeading(type), doc: adaptDocumentable(type, linkGenerator, baseHeadingLevel + 1), name: type.name, meta: { accessModifier: type.access_modifier } }; } function enumTypeToEnumSource(enumType, linkGenerator, baseHeadingLevel = 1, translations) { return __spreadProps$n(__spreadValues$n({ type: "enum" }, baseTypeAdapter(enumType, linkGenerator, baseHeadingLevel, translations)), { values: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.sections.values, value: enumType.values.map((value) => { var _a; return __spreadProps$n(__spreadValues$n({}, adaptDescribable((_a = value.docComment) == null ? void 0 : _a.descriptionLines, linkGenerator)), { value: value.name }); }) } }); } function interfaceTypeToInterfaceSource(interfaceType, linkGenerator, baseHeadingLevel = 1, translations) { return __spreadProps$n(__spreadValues$n({ type: "interface" }, baseTypeAdapter(interfaceType, linkGenerator, baseHeadingLevel, translations)), { extends: interfaceType.extended_interfaces.map(linkGenerator), methods: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.sections.methods, value: interfaceType.methods.map( (method) => adaptMethod(method, linkGenerator, baseHeadingLevel + 2, translations) ) } }); } function classTypeToClassSource(classType, linkGenerator, baseHeadingLevel = 1, translations) { return __spreadProps$n(__spreadValues$n({ type: "class" }, baseTypeAdapter(classType, linkGenerator, baseHeadingLevel, translations)), { classModifier: classType.classModifier, sharingModifier: classType.sharingModifier, implements: classType.implemented_interfaces.map(linkGenerator), extends: classType.inheritanceChain.map(linkGenerator), methods: adaptMembers( translations.markdown.sections.methods, classType.methods, adaptMethod, linkGenerator, baseHeadingLevel + 1, translations ), constructors: adaptMembers( translations.markdown.sections.constructors, classType.constructors, (constructor, linkGenerator2, baseHeadingLevel2, translations2) => adaptConstructor(classType.name, constructor, linkGenerator2, baseHeadingLevel2, translations2), linkGenerator, baseHeadingLevel + 1, translations ), fields: adaptMembers( translations.markdown.sections.fields, classType.fields, adaptFieldOrProperty, linkGenerator, baseHeadingLevel + 1, translations ), properties: adaptMembers( translations.markdown.sections.properties, classType.properties, adaptFieldOrProperty, linkGenerator, baseHeadingLevel + 1, translations ), innerClasses: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.sections.classes, value: classType.classes.map( (innerClass) => classTypeToClassSource( __spreadProps$n(__spreadValues$n({}, innerClass), { inheritanceChain: [] }), linkGenerator, baseHeadingLevel + 2, translations ) ) }, innerEnums: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.sections.enums, value: classType.enums.map( (innerEnum) => enumTypeToEnumSource(innerEnum, linkGenerator, baseHeadingLevel + 2, translations) ) }, innerInterfaces: { headingLevel: baseHeadingLevel + 1, heading: translations.markdown.sections.interfaces, value: classType.interfaces.map( (innerInterface) => interfaceTypeToInterfaceSource(innerInterface, linkGenerator, baseHeadingLevel + 2, translations) ) } }); } function adaptMembers(heading, members, adapter, linkFromTypeNameGenerator, headingLevel, translations) { return { headingLevel, heading, isGrouped: hasGroup(members), value: hasGroup(members) ? toGroupedMembers(members, adapter, linkFromTypeNameGenerator, headingLevel + 1, translations) : toFlat(members, adapter, linkFromTypeNameGenerator, headingLevel + 1, translations) }; } function hasGroup(members) { return members.some((member) => member.group); } function toFlat(members, adapter, linkGenerator, baseHeadingLevel, translations) { return members.map((member) => adapter(member, linkGenerator, baseHeadingLevel, translations)); } function toGroupedMembers(members, adapter, linkGenerator, baseHeadingLevel, translations) { const groupedMembers = groupByGroupName(members); return Object.entries(groupedMembers).map( ([groupName, members2]) => singleGroup(baseHeadingLevel, groupName, adapter, members2, linkGenerator, translations) ); } function groupByGroupName(members) { return members.reduce( (acc, member) => { var _a, _b; const groupName = (_a = member.group) != null ? _a : "Other"; acc[groupName] = (_b = acc[groupName]) != null ? _b : []; acc[groupName].push(member); return acc; }, {} ); } function singleGroup(headingLevel, groupName, adapter, members, linkGenerator, translations) { return { headingLevel, heading: groupName, groupDescription: members[0].groupDescription, // All fields in the group have the same description value: toFlat(members, adapter, linkGenerator, headingLevel + 1, translations) }; } function triggerMetadataToRenderable(triggerMetadata, linkGenerator, baseHeadingLevel = 1, translations) { function formatEvent(event) { switch (event) { case "beforeinsert": return translations.markdown.triggerEvents.beforeInsert; case "beforeupdate": return translations.markdown.triggerEvents.beforeUpdate; case "beforedelete": return translations.markdown.triggerEvents.beforeDelete; case "afterinsert": return translations.markdown.triggerEvents.afterInsert; case "afterupdate": return translations.markdown.triggerEvents.afterUpdate; case "afterdelete": return translations.markdown.triggerEvents.afterDelete; case "afterundelete": return translations.markdown.triggerEvents.afterUndelete; default: return event; } } return { doc: adaptDocumentable( { docComment: triggerMetadata.docComment, annotations: [] }, linkGenerator, baseHeadingLevel + 1 ), name: triggerMetadata.name, type: "trigger", headingLevel: 1, heading: triggerMetadata.name + " " + translations.markdown.typeSuffixes.trigger, objectName: triggerMetadata.object_name, events: triggerMetadata.events.map(formatEvent) }; } function objectMetadataToRenderable(objectMetadata, config, translations) { var _a; function toRenderablePublishBehavior(publishBehavior) { switch (publishBehavior) { case "PublishImmediately": return translations.markdown.publishBehaviors.publishImmediately; case "PublishAfterCommit": return translations.markdown.publishBehaviors.publishAfterCommit; default: return null; } } return { type: "customobject", headingLevel: 1, apiName: getApiName(objectMetadata.name, config), heading: (_a = objectMetadata.label) != null ? _a : objectMetadata.name, name: objectMetadata.name, doc: { description: objectMetadata.description ? [objectMetadata.description] : [], group: getTypeGroup(objectMetadata, config) }, hasFields: objectMetadata.fields.length > 0, fields: { headingLevel: 2, heading: translations.markdown.sections.fields, value: objectMetadata.fields.map((field) => fieldMetadataToRenderable(field, config, 3, translations)) }, hasRecords: objectMetadata.metadataRecords.length > 0, metadataRecords: { headingLevel: 2, heading: translations.markdown.sections.records, value: objectMetadata.metadataRecords.map((metadata) => customMetadataToRenderable(metadata, 3)) }, publishBehavior: toRenderablePublishBehavior(objectMetadata.publishBehavior) }; } function fieldMetadataToRenderable(field, config, headingLevel, translations) { var _a; return { type: "field", headingLevel, heading: (_a = field.label) != null ? _a : field.name, description: field.description ? [field.description] : [], apiName: getApiName(field.name, config), fieldType: field.type, required: field.required, complianceGroup: renderComplianceGroup(field.complianceGroup, config), securityClassification: renderComplianceGroup(field.securityClassification, config), inlineHelpText: renderInlineHelpText(field.inlineHelpText, config), pickListValues: field.pickListValues ? { headingLevel: headingLevel + 1, heading: translations.markdown.details.possibleValues, value: field.pickListValues } : void 0 }; } function customMetadataToRenderable(metadata, headingLevel) { var _a, _b; return { type: "metadata", headingLevel, heading: (_a = metadata.label) != null ? _a : metadata.name, apiName: metadata.apiName, label: (_b = metadata.label) != null ? _b : metadata.name, protected: metadata.protected }; } function getApiName(currentName, config) { if (config.namespace) { const name = currentName.replace(/__c$/, ""); if (name.includes("__")) { return name; } return `${config.namespace}__${currentName}`; } return currentName; } function renderComplianceGroup(complianceGroup, config) { if (config.includeFieldSecurityMetadata) { return complianceGroup; } else { return null; } } function renderInlineHelpText(inlineHelpText, config) { if (config.includeInlineHelpTextMetadata) { return inlineHelpText; } else { return null; } } const generateLink = (strategy) => { switch (strategy) { case "relative": return generateRelativeLink; case "no-link": return generateNoLink; case "none": return returnReferenceAsIs; } }; const generateRelativeLink = (references, from, referenceName) => { function getRelativePath(fromPath, toPath) { return path.relative(path.parse(path.join("/", fromPath)).dir, path.join("/", toPath)); } const referenceTo = references[referenceName]; if (!referenceTo) { return referenceName; } if (referenceTo && from === "__base__") { return { __type: "link", title: referenceTo.displayName, url: getRelativePath("", referenceTo.referencePath) }; } const referenceFrom = references[from]; if (!referenceFrom) { return referenceTo.displayName; } return { __type: "link", title: referenceTo.displayName, url: getRelativePath(referenceFrom.referencePath, referenceTo.referencePath) }; }; const generateNoLink = (references, _from, referenceName) => { const referenceTo = references[referenceName]; return referenceTo ? referenceTo.displayName : referenceName; }; const returnReferenceAsIs = (references, _from, referenceName) => { const referenceTo = references[referenceName]; if (!referenceTo) { return referenceName; } return { __type: "link", title: referenceTo.displayName, url: referenceTo.referencePath }; }; function parsedFilesToRenderableBundle(config, parsedFiles, references, translations) { const referenceFinder = apply(generateLink(config.linkingStrategy), references); function toReferenceGuide(parsedFiles2) { return parsedFiles2.reduce( addToReferenceGuide(apply(referenceFinder, "__base__"), config, references), {} ); } function toRenderables(parsedFiles2) { return parsedFiles2.reduce((acc, parsedFile) => { const renderable = typeToRenderable$1( parsedFile, apply(referenceFinder, parsedFile.source.name), config, translations ); acc.push(renderable); return acc; }, []); } return { referencesByGroup: toReferenceGuide(parsedFiles), renderables: toRenderables(parsedFiles) }; } function addToReferenceGuide(findLinkFromHome, config, references) { return (acc, parsedFile) => { const group = getTypeGroup(parsedFile.type, config); if (!acc[group]) { acc[group] = []; } acc[group].push({ reference: references[parsedFile.source.name], title: findLinkFromHome(parsedFile.source.name), description: getRenderableDescription(parsedFile.type, findLinkFromHome) }); return acc; }; } function getRenderableDescription(type, findLinkFromHome) { var _a, _b; switch (type.type_name) { case "customobject": return type.description ? [type.description] : null; default: return (_b = adaptDescribable((_a = type.docComment) == null ? void 0 : _a.descriptionLines, findLinkFromHome).description) != null ? _b : null; } } class ReflectionError { constructor(file, message) { this.file = file; this.message = message; } } class ReflectionErrors { constructor(errors) { this.errors = errors; this._tag = "ReflectionErrors"; } } class HookError { constructor(error) { this.error = error; this._tag = "HookError"; } } function parseApexMetadata(input) { return _function.pipe(input, parse, E__namespace.map(toMap)); } function parse(input) { return E__namespace.tryCatch(() => new fastXmlParser.XMLParser().parse(input), E__namespace.toError); } function toMap(metadata) { const map = /* @__PURE__ */ new Map(); map.set("apiVersion", String(metadata.ApexClass.apiVersion)); if (metadata.ApexClass.status) { map.set("status", String(metadata.ApexClass.status)); } return map; } var __defProp$m = Object.defineProperty; var __defProps$m = Object.defineProperties; var __getOwnPropDescs$m = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$m = Object.getOwnPropertySymbols; var __hasOwnProp$m = Object.prototype.hasOwnProperty; var __propIsEnum$m = Object.prototype.propertyIsEnumerable; var __defNormalProp$m = (obj, key, value) => key in obj ? __defProp$m(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$m = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$m.call(b, prop)) __defNormalProp$m(a, prop, b[prop]); if (__getOwnPropSymbols$m) for (var prop of __getOwnPropSymbols$m(b)) { if (__propIsEnum$m.call(b, prop)) __defNormalProp$m(a, prop, b[prop]); } return a; }; var __spreadProps$m = (a, b) => __defProps$m(a, __getOwnPropDescs$m(b)); var __async$5 = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; function reflectAsync$1(rawSource) { return __async$5(this, null, function* () { return new Promise((resolve, reject) => { const result = apexReflection.reflect(rawSource); if (result.typeMirror) { return resolve(result.typeMirror); } else if (result.error) { return reject(result.error); } else { return reject(new Error("Unknown error")); } }); }); } function reflectApexSource(apexBundles) { const semiGroupReflectionError = { concat: (x, y) => new ReflectionErrors([...x.errors, ...y.errors]) }; const Ap = TE__namespace.getApplicativeTaskValidation(T__namespace.ApplyPar, semiGroupReflectionError); return _function.pipe(apexBundles, A__namespace.traverse(Ap)(reflectBundle$1)); } function reflectBundle$1(apexBundle) { const convertToParsedFile = apply(toParsedFile$4, apexBundle.filePath); const withMetadata = apply(addMetadata, apexBundle.metadataContent); return _function.pipe(apexBundle, reflectAsTask$1, TE__namespace.map(convertToParsedFile), TE__namespace.flatMap(withMetadata)); } function reflectAsTask$1(apexBundle) { return TE__namespace.tryCatch( () => reflectAsync$1(apexBundle.content), (error) => new ReflectionErrors([new ReflectionError(apexBundle.filePath, error.message)]) ); } function toParsedFile$4(filePath, typeMirror) { return { source: { filePath, name: typeMirror.name, type: typeMirror.type_name }, type: typeMirror }; } function addMetadata(rawMetadataContent, parsedFile) { return TE__namespace.fromEither( _function.pipe( parsedFile.type, (type) => addFileMetadataToTypeAnnotation(type, rawMetadataContent), E__namespace.map((type) => __spreadProps$m(__spreadValues$m({}, parsedFile), { type })), E__namespace.mapLeft( (error) => errorToReflectionErrors(error, isInSource(parsedFile.source) ? parsedFile.source.filePath : "") ) ) ); } function errorToReflectionErrors(error, filePath) { return new ReflectionErrors([new ReflectionError(filePath, error.message)]); } function addFileMetadataToTypeAnnotation(type, metadata) { const concatAnnotationToType = apply(concatAnnotations, type); return _function.pipe( O__namespace.fromNullable(metadata), O__namespace.map(concatAnnotationToType), O__namespace.getOrElse(() => E__namespace.right(type)) ); } function concatAnnotations(type, metadataInput) { return _function.pipe( metadataInput, parseApexMetadata, E__namespace.map((metadataMap) => __spreadProps$m(__spreadValues$m({}, type), { annotations: [...type.annotations, ...mapToAnnotations(metadataMap)] })) ); } function mapToAnnotations(metadata) { return Array.from(metadata.entries()).map(([key, value]) => { const declaration = `${key}: ${value}`; return { name: declaration, type: declaration, rawDeclaration: declaration }; }); } function createInheritanceChain(repository, classMirror) { return _function.pipe( O__namespace.fromNullable(classMirror.extended_class), O__namespace.match( () => [], (extendedClassName) => inheritanceChainFromParentClassName(repository, extendedClassName) ) ); } function inheritanceChainFromParentClassName(repository, className) { return _function.pipe( O__namespace.fromNullable(repository.find((type) => type.name.toLowerCase() === className.toLowerCase())), O__namespace.match( () => [className], (extendedClass) => [className, ...createInheritanceChain(repository, extendedClass)] ) ); } const parsedFilesToTypes = (parsedFiles) => parsedFiles.map((parsedFile) => parsedFile.type); var __defProp$l = Object.defineProperty; var __defProps$l = Object.defineProperties; var __getOwnPropDescs$l = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$l = Object.getOwnPropertySymbols; var __hasOwnProp$l = Object.prototype.hasOwnProperty; var __propIsEnum$l = Object.prototype.propertyIsEnumerable; var __defNormalProp$l = (obj, key, value) => key in obj ? __defProp$l(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$l = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$l.call(b, prop)) __defNormalProp$l(a, prop, b[prop]); if (__getOwnPropSymbols$l) for (var prop of __getOwnPropSymbols$l(b)) { if (__propIsEnum$l.call(b, prop)) __defNormalProp$l(a, prop, b[prop]); } return a; }; var __spreadProps$l = (a, b) => __defProps$l(a, __getOwnPropDescs$l(b)); const addInheritanceChainToTypes = (parsedFiles) => parsedFiles.map((parsedFile) => __spreadProps$l(__spreadValues$l({}, parsedFile), { type: addInheritanceChain(parsedFile.type, parsedFilesToTypes(parsedFiles)) })); function addInheritanceChain(current, repository) { if (current.type_name === "enum" || current.type_name === "interface") { return current; } else { const inheritanceChain = createInheritanceChain(repository, current); return __spreadProps$l(__spreadValues$l({}, current), { inheritanceChain }); } } var __defProp$k = Object.defineProperty; var __defProps$k = Object.defineProperties; var __getOwnPropDescs$k = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols$k = Object.getOwnPropertySymbols; var __hasOwnProp$k = Object.prototype.hasOwnProperty; var __propIsEnum$k = Object.prototype.propertyIsEnumerable; var __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues$k = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp$k.call(b, prop)) __defNormalProp$k(a, prop, b[prop]); if (__getOwnPropSymbols$k) for (var prop of __getOwnPropSymbols$k(b)) { if (__propIsEnum$k.call(b, prop)) __defNormalProp$k(a, prop, b[prop]); } return a; }; var __spreadProps$k = (a, b) => __defProps$k(a, __getOwnPropDescs$k(b)); const addInheritedMembersToTypes = (parsedFiles) => parsedFiles.map((parsedFile) => addInheritedMembers(parsedFilesToTypes(parsedFiles), parsedFile)); function addInheritedMembers(repository, parsedFile) { function addInheritedMembersToType(repository2, current) { if (current.type_name === "enum") { return current; } else if (current.type_name === "interface") { return addInheritedInterfaceMethods(current, repository2); } else { return addInheritedClassMembers(current, repository2); } } return __spreadProps$k(__spreadValues$k({}, parsedFile), { type: addInheritedMembersToType(repository, parsedFile.type) }); } function addInheritedInterfaceMethods(interfaceMirror, repository) { function methodAlreadyExists(memberName, members) { return members.some((member) => member.name.toLowerCase() === memberName.toLowerCase()); } function parentExtractor(interfaceMirror2) { return interfaceMirror2.extended_interfaces; } const parents = getParents(parentExtractor, interfaceMirror, repository); return __spreadProps$k(__spreadValues$k({}, interfaceMirror), { methods: parents.reduce( (acc, currentValue) => [ ...acc, ...currentValue.methods.filter((method) => !methodAlreadyExists(method.name, acc)).map((method) => __spreadProps$k(__spreadValues$k({}, method), { inherited: true })) ], interfaceMirror.methods ) }); } function addInheritedClassMembers(classMirror, repository) { function memberAlreadyExists(memberName, members) { return members.some((member) => member.name.toLowerCase() === memberName.toLowerCase()); } function parentExtractor(classMirror2) { return classMirror2.extended_class ? [classMirror2.extended_class] : []; } function filterMember(members, existing) { return members.filter((member) => member.access_modifier.toLowerCase() !== "private").filter((member) => !memberAlreadyExists(member.name, existing)).map((member) => __spreadProps$k(__spreadValues$k({}, member), { inherited: true })); } const parents = getParents(parentExtractor, classMirror, repository); return __spreadProps$k(__spreadValues$k({}, classMirror), { fields: parents.reduce( (acc, currentValue) => [...acc, ...filterMember(currentValue.fields, acc)], classMirror.fields ), properties: parents.reduce( (acc, currentValue) => [...acc, ...filterMember(currentValue.properties, acc)], classMirror.properties ), methods: parents.reduce( (acc, currentValue) => [...acc, ...filterMember(currentValue.methods, acc)], classMirror.methods ) }); } function getParents(extendedNamesExtractor, current, repository) { return _function.pipe( extendedNamesExtractor(current), (interfaces) => interfaces.map((interfaceName) => repository.find((type) => type.name === interfaceName)), (interfaces = []) => interfaces.filter((type) => type !== void 0), (interfaces) => interfaces.reduce( (acc, current2) => [...acc, ...getParents(extendedNamesExtractor, current2, repository)], interfaces ) ); } const typeDocPartial = ` {{#> documentablePartialTemplate}} {{#if doc.group}} **{{@root.translations.markdown.details.group}}** {{doc.group}} {{/if}} {{#if doc.author}} **{{@root.translations.markdown.details.author}}** {{doc.author}} {{/if}} {{#if doc.date}} **{{@root.translations.markdown.details.date}}** {{doc.date}} {{/if}} {{#each doc.sees}} **{{@root.translations.markdown.details.see}}** {{link this}} {{/each}} {{#if namespace}} ## {{@root.translations.markdown.sections.namespace}} {{namespace}} {{/if}} {{/documentablePartialTemplate}} `.trim(); const documentablePartialTemplate = ` {{#each doc.annotations}} \`{{this}}\` {{/each}} {{{renderContent doc.description}}} {{#each doc.customTags}} **{{splitAndCapitalize name}}** {{{renderContent description}}} {{/each}} {{> @partial-block}} {{#if doc.mermaid.value}} {{ heading doc.mermaid.headingLevel doc.mermaid.heading }} {{code doc.mermaid.value}} {{/if}} {{#if doc.example.value}} {{ heading doc.example.headingLevel doc.example.heading }} {{{renderContent doc.example.value}}} {{/if}} `.trim(); const methodsPartialTemplate = ` {{ heading headingLevel heading }} {{#each value}} {{{ heading headingLevel (inlineCode heading) }}} {{#if inherited}} *Inherited* {{/if}} {{#> documentablePartialTemplate}} {{ heading signature.headingLevel signature.heading }} {{ code signature.value }} {{#if parameters.value}} {{ heading parameters.headingLevel parameters.heading }} | Name | Type | Description | |------|------|-------------| {{#each parameters.value}} | {{name}} | {{link type}} | {{{renderContent description}}} | {{/each}} {{/if}} {{ heading returnType.headingLevel returnType.heading }} **{{link returnType.value.typ