diff --git a/examples/markdown/docs/custom-objects/Account.md b/examples/markdown/docs/custom-objects/Account.md
new file mode 100644
index 00000000..af6d2715
--- /dev/null
+++ b/examples/markdown/docs/custom-objects/Account.md
@@ -0,0 +1,4 @@
+# Account
+
+## API Name
+`ns__Account`
\ No newline at end of file
diff --git a/examples/markdown/docs/custom-objects/Contact.md b/examples/markdown/docs/custom-objects/Contact.md
new file mode 100644
index 00000000..27086047
--- /dev/null
+++ b/examples/markdown/docs/custom-objects/Contact.md
@@ -0,0 +1,15 @@
+# Contact
+
+## API Name
+`ns__Contact`
+
+## Fields
+### PhotoUrl
+
+**API Name**
+
+`ns__PhotoUrl__c`
+
+**Type**
+
+*Url*
\ No newline at end of file
diff --git a/examples/markdown/docs/index.md b/examples/markdown/docs/index.md
index bc012275..fb757332 100644
--- a/examples/markdown/docs/index.md
+++ b/examples/markdown/docs/index.md
@@ -2,6 +2,10 @@
## Custom Objects
+### [Account](custom-objects/Account.md)
+
+### [Contact](custom-objects/Contact.md)
+
### [Event__c](custom-objects/Event__c.md)
Represents an event that people can register for.
diff --git a/examples/markdown/force-app/objects/Account/Account.object-meta.xml b/examples/markdown/force-app/objects/Account/Account.object-meta.xml
new file mode 100644
index 00000000..5f969ba5
--- /dev/null
+++ b/examples/markdown/force-app/objects/Account/Account.object-meta.xml
@@ -0,0 +1,90 @@
+
+
+
+ CallHighlightAction
+ Default
+
+
+ CancelEdit
+ Default
+
+
+ Delete
+ Default
+
+
+ Edit
+ Default
+
+
+ EmailHighlightAction
+ Default
+
+
+ EnableCustomerPortalUser
+ Default
+
+
+ List
+ Default
+
+
+ ListClean
+ Default
+
+
+ New
+ Default
+
+
+ RequestUpdate
+ Default
+
+
+ SaveEdit
+ Default
+
+
+ SmsHighlightAction
+ Default
+
+
+ Tab
+ Default
+
+
+ View
+ Account_Record_Page
+ Large
+ false
+ Flexipage
+
+
+ ViewCustomerPortalUser
+ Default
+
+
+ WebsiteHighlightAction
+ Default
+
+ Account_Compact_Layout
+ true
+ true
+ false
+
+ ACCOUNT.NAME
+ ACCOUNT.ADDRESS1_CITY
+ ACCOUNT.PHONE1
+ ACCOUNT.NAME
+ CORE.USERS.ALIAS
+ ACCOUNT.TYPE
+ ACCOUNT.NAME
+ CORE.USERS.ALIAS
+ ACCOUNT.TYPE
+ ACCOUNT.PHONE1
+ ACCOUNT.NAME
+ ACCOUNT.PHONE1
+ CORE.USERS.ALIAS
+
+ ReadWrite
+
diff --git a/examples/markdown/force-app/objects/Contact/Contact.object-meta.xml b/examples/markdown/force-app/objects/Contact/Contact.object-meta.xml
new file mode 100644
index 00000000..0d11ee1b
--- /dev/null
+++ b/examples/markdown/force-app/objects/Contact/Contact.object-meta.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/package.json b/package.json
index 43b8a745..2c269126 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@cparra/apexdocs",
- "version": "3.4.1",
+ "version": "3.4.2",
"description": "Library with CLI capabilities to generate documentation for Salesforce Apex classes.",
"keywords": [
"apex",
diff --git a/src/application/source-code-file-reader.ts b/src/application/source-code-file-reader.ts
index 7d9b5da3..2a4e6071 100644
--- a/src/application/source-code-file-reader.ts
+++ b/src/application/source-code-file-reader.ts
@@ -155,7 +155,16 @@ export function processFiles(fileSystem: FileSystem) {
return (rootPath: string, exclude: string[]) => {
return pipe(
fileSystem.getComponents(rootPath),
- (components) => components.filter((component) => !isExcluded(component.content!, exclude)),
+ (components) => {
+ return components.map((component) => {
+ const pathLocation = component.type.name === 'ApexClass' ? component.content : component.xml;
+ return {
+ ...component,
+ filePath: pathLocation!,
+ };
+ });
+ },
+ (components) => components.filter((component) => !isExcluded(component.filePath, exclude)),
(components) => convertersToUse.map((converter) => converter(components)),
(bundles) => bundles.flat(),
);
diff --git a/src/core/markdown/adapters/type-to-renderable.ts b/src/core/markdown/adapters/type-to-renderable.ts
index cd66d8ec..286a09b9 100644
--- a/src/core/markdown/adapters/type-to-renderable.ts
+++ b/src/core/markdown/adapters/type-to-renderable.ts
@@ -254,7 +254,7 @@ function objectMetadataToRenderable(
type: 'customobject',
headingLevel: 1,
apiName: getApiName(objectMetadata.name, config),
- heading: objectMetadata.label,
+ heading: objectMetadata.label ?? objectMetadata.name,
name: objectMetadata.name,
doc: {
description: objectMetadata.description ? [objectMetadata.description] : [],
@@ -277,7 +277,7 @@ function fieldMetadataToRenderable(
return {
type: 'field',
headingLevel: headingLevel,
- heading: field.label,
+ heading: field.label ?? field.name,
description: field.description ? [field.description] : [],
apiName: getApiName(field.name, config),
fieldType: field.type,
diff --git a/src/core/markdown/templates/custom-object-template.ts b/src/core/markdown/templates/custom-object-template.ts
index ff0af90b..bedc7f41 100644
--- a/src/core/markdown/templates/custom-object-template.ts
+++ b/src/core/markdown/templates/custom-object-template.ts
@@ -19,9 +19,11 @@ export const customObjectTemplate = `
\`{{{apiName}}}\`
+{{#if fieldType}}
**Type**
*{{fieldType}}*
+{{/if}}
{{#unless @last}}---{{/unless}}
{{/each}}
diff --git a/src/core/reflection/sobject/__test__/reflect-custom-field-sources.spec.ts b/src/core/reflection/sobject/__test__/reflect-custom-field-sources.spec.ts
index 0eba7e3c..0a621483 100644
--- a/src/core/reflection/sobject/__test__/reflect-custom-field-sources.spec.ts
+++ b/src/core/reflection/sobject/__test__/reflect-custom-field-sources.spec.ts
@@ -137,66 +137,4 @@ describe('when parsing custom field metadata', () => {
expect(E.isLeft(result)).toBe(true);
});
-
- test('An error is returned when the CustomField key is not an object', async () => {
- const unparsed: UnparsedCustomFieldBundle = {
- type: 'customfield',
- name: 'PhotoUrl__c',
- parentName: 'MyFirstObject__c',
- filePath: 'src/field/PhotoUrl__c.field-meta.xml',
- content: `
-
- invalid`,
- };
-
- const result = await reflectCustomFieldSources([unparsed])();
-
- expect(E.isLeft(result)).toBe(true);
- });
-
- test('An error is returned when the CustomKey object does not contain the label key', async () => {
- const unparsed: UnparsedCustomFieldBundle = {
- type: 'customfield',
- name: 'PhotoUrl__c',
- parentName: 'MyFirstObject__c',
- filePath: 'src/field/PhotoUrl__c.field-meta.xml',
- content: `
-
-
- PhotoUrl__c
- false
- false
- false
- Url
- A Photo URL field
- `,
- };
-
- const result = await reflectCustomFieldSources([unparsed])();
-
- expect(E.isLeft(result)).toBe(true);
- });
-
- test('An error is returned when the CustomKey object does not contain the type key', async () => {
- const unparsed: UnparsedCustomFieldBundle = {
- type: 'customfield',
- name: 'PhotoUrl__c',
- parentName: 'MyFirstObject__c',
- filePath: 'src/field/PhotoUrl__c.field-meta.xml',
- content: `
-
-
- PhotoUrl__c
- false
-
- false
- false
- A Photo URL field
- `,
- };
-
- const result = await reflectCustomFieldSources([unparsed])();
-
- expect(E.isLeft(result)).toBe(true);
- });
});
diff --git a/src/core/reflection/sobject/__test__/reflect-custom-object-sources.spec.ts b/src/core/reflection/sobject/__test__/reflect-custom-object-sources.spec.ts
index f923feee..b02f10bc 100644
--- a/src/core/reflection/sobject/__test__/reflect-custom-object-sources.spec.ts
+++ b/src/core/reflection/sobject/__test__/reflect-custom-object-sources.spec.ts
@@ -156,26 +156,4 @@ describe('when parsing SObject metadata', () => {
expect(E.isLeft(result)).toBe(true);
});
-
- test('an error is thrown when the label is missing', async () => {
- const sObjectContent = `
-
-
- Deployed
- test object for testing
- MyFirstObjects
- Public
- `;
-
- const unparsed: UnparsedCustomObjectBundle = {
- type: 'customobject',
- name: 'MyFirstObject__c',
- filePath: 'src/object/MyFirstObject__c.object-meta.xml',
- content: sObjectContent,
- };
-
- const result = await reflectCustomObjectSources([unparsed])();
-
- expect(E.isLeft(result)).toBe(true);
- });
});
diff --git a/src/core/reflection/sobject/reflect-custom-field-source.ts b/src/core/reflection/sobject/reflect-custom-field-source.ts
index a0affa80..c42f78fc 100644
--- a/src/core/reflection/sobject/reflect-custom-field-source.ts
+++ b/src/core/reflection/sobject/reflect-custom-field-source.ts
@@ -12,8 +12,8 @@ export type CustomFieldMetadata = {
type_name: 'customfield';
description: string | null;
name: string;
- label: string;
- type: string;
+ label?: string | null;
+ type?: string | null;
parentName: string;
};
@@ -43,7 +43,7 @@ function reflectCustomFieldSource(
);
}
-function validate(parsedResult: unknown): E.Either {
+function validate(parsedResult: unknown): E.Either {
const err = E.left(new Error('Invalid custom field metadata'));
function isObject(value: unknown) {
@@ -54,34 +54,16 @@ function validate(parsedResult: unknown): E.Either) {
- return typeof value.CustomField === 'object' ? E.right(value as Record<'CustomField', object>) : err;
- }
-
- function theCustomFieldObjectContainsTheLabelKey(value: Record<'CustomField', object>) {
- return 'label' in value.CustomField ? E.right(value) : err;
- }
-
- function theCustomFieldObjectContainsTheTypeKey(value: Record<'CustomField', object>) {
- return 'type' in value.CustomField ? E.right(value) : err;
- }
-
- return pipe(
- parsedResult,
- isObject,
- E.chain(hasTheCustomFieldKey),
- E.chain(theCustomFieldKeyIsAnObject),
- E.chain(theCustomFieldObjectContainsTheLabelKey),
- E.chain(theCustomFieldObjectContainsTheTypeKey),
- );
+ return pipe(parsedResult, isObject, E.chain(hasTheCustomFieldKey));
}
-function toCustomFieldMetadata(parserResult: { CustomField: object }): CustomFieldMetadata {
+function toCustomFieldMetadata(parserResult: { CustomField: unknown }): CustomFieldMetadata {
+ const customField = typeof parserResult.CustomField === 'object' ? parserResult.CustomField : {};
const defaultValues = {
description: null,
};
- return { ...defaultValues, ...parserResult.CustomField, type_name: 'customfield' } as CustomFieldMetadata;
+ return { ...defaultValues, ...customField, type_name: 'customfield' } as CustomFieldMetadata;
}
function addName(metadata: CustomFieldMetadata, name: string): CustomFieldMetadata {
diff --git a/src/core/reflection/sobject/reflect-custom-object-sources.ts b/src/core/reflection/sobject/reflect-custom-object-sources.ts
index e301c4c1..8ddfe459 100644
--- a/src/core/reflection/sobject/reflect-custom-object-sources.ts
+++ b/src/core/reflection/sobject/reflect-custom-object-sources.ts
@@ -13,7 +13,7 @@ export type ObjectMetadata = {
type_name: 'customobject';
deploymentStatus: string;
visibility: string;
- label: string;
+ label?: string | null;
name: string;
description: string | null;
fields: ParsedFile[];
@@ -45,7 +45,7 @@ function reflectCustomObjectSource(
);
}
-function validate(parseResult: unknown): E.Either {
+function validate(parseResult: unknown): E.Either {
const err = E.left(new Error('Invalid SObject metadata'));
function isObject(value: unknown) {
@@ -56,31 +56,19 @@ function validate(parseResult: unknown): E.Either) {
- return typeof value.CustomObject === 'object' ? E.right(value as Record<'CustomObject', object>) : err;
- }
-
- function theCustomObjectContainsTheLabelKey(value: Record<'CustomObject', object>) {
- return 'label' in value.CustomObject ? E.right(value) : err;
- }
-
- return pipe(
- parseResult,
- isObject,
- E.chain(hasTheCustomObjectKey),
- E.chain(theCustomObjectKeyIsAnObject),
- E.chain(theCustomObjectContainsTheLabelKey),
- );
+ return pipe(parseResult, isObject, E.chain(hasTheCustomObjectKey));
}
-function toObjectMetadata(parserResult: { CustomObject: object }): ObjectMetadata {
+function toObjectMetadata(parserResult: { CustomObject: unknown }): ObjectMetadata {
+ const customObject = typeof parserResult.CustomObject === 'object' ? parserResult.CustomObject : {};
+
const defaultValues = {
deploymentStatus: 'Deployed',
visibility: 'Public',
description: null,
fields: [] as ParsedFile[],
};
- return { ...defaultValues, ...parserResult.CustomObject } as ObjectMetadata;
+ return { ...defaultValues, ...customObject } as ObjectMetadata;
}
function addName(objectMetadata: ObjectMetadata, name: string): ObjectMetadata {
diff --git a/src/core/renderables/types.d.ts b/src/core/renderables/types.d.ts
index ddf50728..cfdc58a8 100644
--- a/src/core/renderables/types.d.ts
+++ b/src/core/renderables/types.d.ts
@@ -190,7 +190,7 @@ export type RenderableCustomField = {
apiName: string;
description: RenderableContent[];
type: 'field';
- fieldType: string;
+ fieldType?: string | null;
};
export type Renderable = (RenderableClass | RenderableInterface | RenderableEnum | RenderableCustomObject) & {