@cparra/apexdocs
Version:
Library with CLI capabilities to generate documentation for Salesforce Apex classes.
677 lines (605 loc) • 20 kB
TypeScript
/**
* Default English translations for ApexDocs.
* These can be overridden by users in their configuration.
*/
type Translations = {
changelog: {
title: string;
newClasses: {
heading: string;
description: string;
};
newInterfaces: {
heading: string;
description: string;
};
newEnums: {
heading: string;
description: string;
};
newCustomObjects: {
heading: string;
description: string;
};
newTriggers: {
heading: string;
description: string;
};
removedTypes: {
heading: string;
description: string;
};
removedCustomObjects: {
heading: string;
description: string;
};
removedTriggers: {
heading: string;
description: string;
};
newOrModifiedMembers: {
heading: string;
description: string;
};
newOrRemovedCustomFields: {
heading: string;
description: string;
};
newOrRemovedCustomMetadataTypeRecords: {
heading: string;
description: string;
};
memberModifications: {
newEnumValue: string;
removedEnumValue: string;
newMethod: string;
removedMethod: string;
newProperty: string;
removedProperty: string;
newField: string;
removedField: string;
newType: string;
removedType: string;
newCustomMetadataRecord: string;
removedCustomMetadataRecord: string;
newTrigger: string;
removedTrigger: string;
};
};
markdown: {
sections: {
methods: string;
properties: string;
fields: string;
constructors: string;
values: string;
classes: string;
enums: string;
interfaces: string;
namespace: string;
records: string;
publishBehavior: string;
};
details: {
type: string;
signature: string;
group: string;
author: string;
date: string;
see: string;
possibleValues: string;
parameters: string;
throws: string;
returnType: string;
apiName: string;
required: string;
inlineHelpText: string;
complianceGroup: string;
securityClassification: string;
protected: string;
};
typeSuffixes: {
class: string;
interface: string;
enum: string;
trigger: string;
};
triggerEvents: {
beforeInsert: string;
beforeUpdate: string;
beforeDelete: string;
afterInsert: string;
afterUpdate: string;
afterDelete: string;
afterUndelete: string;
};
publishBehaviors: {
publishImmediately: string;
publishAfterCommit: string;
};
inheritance: {
inheritance: string;
implements: string;
};
lwc: {
exposed: string;
targets: string;
targetConfigs: string;
properties: string;
};
};
};
/**
* User-provided partial translations that can override the defaults.
*/
type UserTranslations = DeepPartial<Translations>;
/**
* Utility type to make all properties in T optional recursively.
*/
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// Apex Reflection-based types
// Renderable types
type ReferenceGuideReference = {
reference: DocPageReference;
title: Link;
description: RenderableContent[] | null;
};
type Link = {
readonly __type: 'link';
title: string;
url: string;
};
type EmptyLine = {
__type: 'empty-line';
};
type StringOrLink = string | Link;
type RenderableContent = StringOrLink | EmptyLine | CodeBlock | InlineCode;
type EnumValue = {
value: string;
description?: RenderableContent[];
};
type CustomTag = {
name: string;
description?: RenderableContent[];
};
/**
* Represents an annotation to a top-level type. For example, @NamespaceAccessible.
*/
type Annotation = string;
type CodeBlock = {
readonly __type: 'code-block';
language: string;
content: string[];
};
type InlineCode = {
readonly __type: 'inline-code';
content: string;
};
type RenderableDocumentation = {
annotations?: Annotation[];
description?: RenderableContent[];
customTags?: CustomTag[];
example?: RenderableSection<RenderableContent[] | undefined>;
group?: string;
author?: string;
date?: string;
sees?: StringOrLink[];
};
type RenderableType = {
namespace?: string;
headingLevel: number;
heading: string;
name: string;
meta: {
accessModifier: string;
};
doc: RenderableDocumentation;
};
type RenderableMethodParameter = {
name: string;
type: StringOrLink;
description?: RenderableContent[];
};
type TypeSource = {
type: StringOrLink;
description?: RenderableContent[];
};
type RenderableConstructor = {
headingLevel: number;
heading: string;
signature: RenderableSection<CodeBlock>;
parameters?: RenderableSection<RenderableMethodParameter[] | undefined>;
throws?: RenderableSection<TypeSource[] | undefined>;
doc: RenderableDocumentation;
};
type RenderableMethod = {
doc: RenderableDocumentation;
headingLevel: number;
heading: string;
signature: RenderableSection<CodeBlock>;
parameters: RenderableSection<RenderableMethodParameter[] | undefined>;
returnType: RenderableSection<TypeSource>;
throws: RenderableSection<TypeSource[] | undefined>;
inherited?: boolean;
};
type RenderableApexField = {
headingLevel: number;
heading: string;
type: RenderableSection<StringOrLink>;
accessModifier: string;
inherited?: boolean;
signature: RenderableSection<CodeBlock>;
doc: RenderableDocumentation;
};
type RenderableSection<T> = {
headingLevel: number;
heading: string;
value: T;
};
type GroupedMember<T> = RenderableSection<T[]> & { groupDescription: string | undefined };
type RenderableClass = RenderableType & {
type: 'class';
extends?: StringOrLink[];
implements?: StringOrLink[];
classModifier?: string;
sharingModifier?: string;
constructors: RenderableSection<RenderableConstructor[] | GroupedMember<RenderableConstructor>[]> & {
isGrouped: boolean;
};
methods: RenderableSection<RenderableMethod[] | GroupedMember<RenderableMethod>[]> & { isGrouped: boolean };
fields: RenderableSection<RenderableApexField[] | GroupedMember<RenderableApexField>[]> & { isGrouped: boolean };
properties: RenderableSection<RenderableApexField[] | GroupedMember<RenderableApexField>[]> & { isGrouped: boolean };
innerClasses: RenderableSection<RenderableClass[]>;
innerEnums: RenderableSection<RenderableEnum[]>;
innerInterfaces: RenderableSection<RenderableInterface[]>;
};
type RenderableInterface = RenderableType & {
type: 'interface';
extends?: StringOrLink[];
methods: RenderableSection<RenderableMethod[]>;
};
type RenderableEnum = RenderableType & {
type: 'enum';
values: RenderableSection<EnumValue[]>;
};
type RenderableTrigger = Omit<RenderableType, 'meta'> & {
type: 'trigger';
objectName: string;
events: string[];
};
type RenderableLwc = Omit<RenderableType, 'meta'> & {
type: 'lwc';
exposed: boolean;
description: string | undefined;
targets: RenderableSection<string[]>;
targetConfigs: RenderableSection<TargetConfigRenderable[]>;
};
type TargetConfigRenderable = {
targetName: string;
properties: {
type: string;
required: boolean;
description: string | undefined;
label: string;
name: string;
}[];
};
type RenderableCustomObject = Omit<RenderableType, 'meta'> & {
apiName: string;
type: 'customobject';
hasFields: boolean;
hasRecords: boolean;
fields: RenderableSection<RenderableCustomField[]>;
metadataRecords: RenderableSection<RenderableCustomMetadata[]>;
publishBehavior: string | null;
};
type RenderableCustomField = {
headingLevel: number;
heading: string;
apiName: string;
description: RenderableContent[];
pickListValues?: RenderableSection<string[]>;
type: 'field';
fieldType?: string | null;
required: boolean;
complianceGroup: string | null;
securityClassification: string | null;
inlineHelpText: string | null;
};
type RenderableCustomMetadata = {
headingLevel: number;
heading: string;
apiName: string;
type: 'metadata';
label: string;
protected: boolean;
};
type Renderable = (
| RenderableClass
| RenderableInterface
| RenderableEnum
| RenderableCustomObject
| RenderableTrigger
| RenderableLwc
) & {
filePath: string | undefined;
};
type Generators = 'markdown' | 'openapi' | 'changelog';
type LinkingStrategy =
// Links will be generated using relative paths.
| 'relative'
// No links will be generated.
// If the reference is found, the display name will be used.
// Otherwise, the name
// of the reference itself will be used.
| 'no-link'
// No logic will be applied, the reference path will be used as is.
| 'none';
type MacroSourceMetadata = {
type: 'apex' | 'customobject' | 'customfield' | 'custommetadata' | 'trigger' | 'lwc';
name: string;
filePath: string;
};
type MacroFunction = (metadata: MacroSourceMetadata) => string;
type CliConfigurableMarkdownConfig = {
sourceDir?: string | string[];
useSfdxProjectJson?: boolean;
sfdxProjectPath?: string;
targetDir: string;
scope: string[];
customObjectVisibility: string[];
namespace?: string;
defaultGroupName: string;
customObjectsGroupName: string;
triggersGroupName: string;
lwcGroupName: string;
sortAlphabetically: boolean;
includeMetadata: boolean;
linkingStrategy: LinkingStrategy;
referenceGuideTitle: string;
includeFieldSecurityMetadata: boolean;
includeInlineHelpTextMetadata: boolean;
experimentalLwcSupport: boolean;
parallelReflection: boolean;
parallelReflectionMaxWorkers?: number;
};
type UserDefinedMarkdownConfig = {
targetGenerator: 'markdown';
excludeTags: string[];
exclude: string[];
translations?: UserTranslations['markdown'];
} & CliConfigurableMarkdownConfig &
Partial<MarkdownConfigurableHooks>;
type UserDefinedOpenApiConfig = {
targetGenerator: 'openapi';
sourceDir?: string | string[];
useSfdxProjectJson?: boolean;
sfdxProjectPath?: string;
targetDir: string;
fileName: string;
namespace?: string;
title: string;
apiVersion: string;
exclude: string[];
parallelReflection: boolean;
parallelReflectionMaxWorkers?: number;
};
type UserDefinedChangelogConfig = {
targetGenerator: 'changelog';
previousVersionDir?: string | string[];
currentVersionDir?: string | string[];
targetDir: string;
fileName: string;
scope: string[];
customObjectVisibility: string[];
exclude: string[];
skipIfNoChanges: boolean;
translations?: UserTranslations['changelog'];
parallelReflection: boolean;
parallelReflectionMaxWorkers?: number;
} & Partial<ChangelogConfigurableHooks>;
type UserDefinedConfig = UserDefinedMarkdownConfig | UserDefinedOpenApiConfig | UserDefinedChangelogConfig;
type MetadataTypes =
| 'interface'
| 'class'
| 'enum'
| 'customobject'
| 'customfield'
| 'custommetadata'
| 'trigger'
| 'lwc';
type SourceFileMetadata = {
filePath: string;
name: string;
type: MetadataTypes;
};
// External metadata is metadata that does not live directly in the source code, and thus we don't
// have a file path for it.
// This is metadata derived from other information.
// For example, for an "extension"
// field that extends a Salesforce object or object in a different package, we want to capture the parent
// object, even if the file for that object was not parsed.
type ExternalMetadata = {
name: string;
type: MetadataTypes;
};
type DocPageReference = {
source: SourceFileMetadata | ExternalMetadata;
// The name under which the type should be displayed in the documentation.
// By default, this will match the source.name, but it can be configured by the user.
displayName: string;
// The location where the file will be written.
outputDocPath: string;
// The path to the file relative to the documentation root directory. This is used when linking to the file.
// Usually the value will be the same as outputDocPath. However, some site generators may have a different way of
// organizing the files, so this allows for the flexibility of having a path from linking that is different from
// the path where the file is written.
referencePath: string;
};
type Frontmatter = string | Record<string, unknown> | null;
type ReferenceGuidePageData = {
frontmatter: Frontmatter;
content: string;
outputDocPath: string;
};
type DocPageData = {
source: SourceFileMetadata | ExternalMetadata;
group: string | null;
outputDocPath: string;
frontmatter: Frontmatter;
content: string;
type: 'class' | 'interface' | 'enum' | 'customobject' | 'trigger' | 'lwc';
};
type FileChange = {
name: string;
fileType: 'apex' | 'customobject';
changeType: 'added' | 'removed' | 'changed';
changes?: {
addedMethods?: string[];
removedMethods?: string[];
addedFields?: string[];
removedFields?: string[];
addedProperties?: string[];
removedProperties?: string[];
addedCustomFields?: string[];
removedCustomFields?: string[];
addedSubtypes?: string[];
removedSubtypes?: string[];
addedEnumValues?: string[];
removedEnumValues?: string[];
};
};
type SourceChangelog = {
fileChanges: FileChange[];
};
type ChangeLogPageData = {
source: SourceChangelog;
frontmatter: Frontmatter;
content: string;
outputDocPath: string;
};
/**
* Represents a file to be skipped.
*/
type Skip = {
readonly _tag: 'Skip';
};
// CONFIGURABLE HOOKS
/**
* Template configuration for customizing markdown output.
*/
type TemplateConfig = {
class?: string | ((renderable: RenderableClass, helpers: TemplateHelpers) => string);
interface?: string | ((renderable: RenderableInterface, helpers: TemplateHelpers) => string);
enum?: string | ((renderable: RenderableEnum, helpers: TemplateHelpers) => string);
trigger?: string | ((renderable: RenderableTrigger, helpers: TemplateHelpers) => string);
lwc?: string | ((renderable: RenderableLwc, helpers: TemplateHelpers) => string);
customObject?: string | ((renderable: RenderableCustomObject, helpers: TemplateHelpers) => string);
referenceGuide?: string | ((data: ReferenceGuideData, helpers: TemplateHelpers) => string);
};
/**
* Template helpers for consistent rendering.
*/
type TemplateHelpers = {
link: (source: StringOrLink) => string;
code: (codeBlock: CodeBlock) => string;
renderContent: (content?: RenderableContent[]) => string;
heading: (level: number, text: string) => string;
inlineCode: (text: string) => string;
eq: (a: unknown, b: unknown) => boolean;
add: (a: number, b: number) => number;
lookup: (array: unknown[], index: number) => unknown;
parseJSON: (jsonString: string) => unknown | null;
startsWith: (str: string, prefix: string) => boolean;
substring: (str: string, start: number, length?: number) => string;
splitAndCapitalize: (text: string) => string;
};
/**
* Data structure passed to reference guide template functions.
*/
type ReferenceGuideData = {
referenceGuideTitle: string;
references: Record<string, ReferenceGuideReference[]>;
};
/**
* The configurable hooks that can be used to modify the output of the Markdown generator.
*/
type MarkdownConfigurableHooks = {
macros: Record<string, MacroFunction>;
transformReferenceGuide: TransformReferenceGuide;
transformDocs: TransformDocs;
transformDocPage: TransformDocPage;
transformReference: TransformReference;
templates?: TemplateConfig;
};
type ConfigurableDocPageReference = Omit<DocPageReference, 'source'>;
type ConfigurableDocPageData = Omit<DocPageData, 'source' | 'outputDocPath'>;
/**
* Allows changing where the files are written to.
*/
type TransformReference = (
reference: DocPageReference,
) => Partial<ConfigurableDocPageReference> | Promise<ConfigurableDocPageReference>;
/**
* Allows changing the frontmatter and content of the reference guide, or even if creating a reference
* guide will be skipped altogether.
*/
type TransformReferenceGuide = (
referenceGuide: ReferenceGuidePageData,
) => Partial<ReferenceGuidePageData> | Skip | Promise<Partial<ReferenceGuidePageData> | Skip>;
/**
* The main purpose if for allowing for doc pages to be skipped, but it can also be used to change the frontmatter
* and content of the doc pages.
*/
type TransformDocs = (docs: DocPageData[]) => DocPageData[] | Promise<DocPageData[]>;
/**
* Allows changing the frontmatter and content of the doc pages.
*/
type TransformDocPage = (
doc: DocPageData,
) => Partial<ConfigurableDocPageData> | Promise<Partial<ConfigurableDocPageData>>;
type ChangelogConfigurableHooks = {
transformChangeLogPage: TransformChangelogPage;
};
type TransformChangelogPage = (
page: ChangeLogPageData,
) => Partial<ChangeLogPageData> | Promise<Partial<ChangeLogPageData>>;
/**
* Represents a file to be skipped.
*/
declare function skip(): Skip;
/**
* Get all template helpers as an object matching TemplateHelpers type.
*/
declare const templateHelpers: TemplateHelpers;
type CallableConfig = Partial<UserDefinedConfig> & {
sourceDir: string;
targetGenerator: Generators;
};
/**
* Processes the documentation generation, similar to the main function in the CLI.
* @param config The configuration to use.
*/
declare function process(config: CallableConfig): Promise<void>;
type ConfigurableMarkdownConfig = Omit<Partial<UserDefinedMarkdownConfig>, 'targetGenerator'>;
/**
* Helper function to define a configuration to generate Markdown documentation.
* @param config The configuration to use.
*/
declare function defineMarkdownConfig(config: ConfigurableMarkdownConfig): Partial<UserDefinedMarkdownConfig>;
type ConfigurableOpenApiConfig = Omit<Partial<UserDefinedOpenApiConfig>, 'targetGenerator'>;
/**
* Helper function to define a configuration to generate OpenAPI documentation.
* @param config The configuration to use.
*/
declare function defineOpenApiConfig(config: ConfigurableOpenApiConfig): Partial<UserDefinedOpenApiConfig>;
type ConfigurableChangelogConfig = Omit<Partial<UserDefinedChangelogConfig>, 'targetGenerator'>;
/**
* Helper function to define a configuration to generate a changelog.
* @param config The configuration to use.
*/
declare function defineChangelogConfig(config: ConfigurableChangelogConfig): Partial<UserDefinedChangelogConfig>;
export { defineChangelogConfig, defineMarkdownConfig, defineOpenApiConfig, process, skip, templateHelpers };
export type { ChangeLogPageData, ChangelogConfigurableHooks, CodeBlock, ConfigurableChangelogConfig, ConfigurableDocPageData, ConfigurableDocPageReference, ConfigurableMarkdownConfig, ConfigurableOpenApiConfig, DocPageData, DocPageReference, GroupedMember, Link, MacroFunction, MacroSourceMetadata, MarkdownConfigurableHooks, ReferenceGuideData, ReferenceGuidePageData, ReferenceGuideReference, Renderable, RenderableApexField, RenderableClass, RenderableConstructor, RenderableContent, RenderableCustomObject, RenderableEnum, RenderableInterface, RenderableLwc, RenderableMethod, RenderableMethodParameter, RenderableSection, RenderableTrigger, Skip, SourceChangelog, StringOrLink, TemplateConfig, TemplateHelpers, TransformChangelogPage, TransformDocPage, TransformDocs, TransformReference, TransformReferenceGuide, Translations, TypeSource, UserTranslations };