@cparra/apexdocs 2.9.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -66
- package/docs/Main/nspc.GroupedClass.md +10 -0
- package/docs/Main/{SampleClass.md → nspc.SampleClass.md} +6 -6
- package/docs/Misc-Group/nspc.AnotherInterface.md +1 -0
- package/docs/Misc-Group/{ChildClass.md → nspc.ChildClass.md} +4 -4
- package/docs/Misc-Group/{GrandparentClass.md → nspc.GrandparentClass.md} +1 -1
- package/docs/Misc-Group/{InterfaceWithInheritance.md → nspc.InterfaceWithInheritance.md} +3 -3
- package/docs/Misc-Group/{ParentClass.md → nspc.ParentClass.md} +2 -2
- package/docs/Misc-Group/{Reference1.md → nspc.Reference1.md} +1 -1
- package/docs/Misc-Group/nspc.Reference2.md +12 -0
- package/docs/Misc-Group/{Reference3.md → nspc.Reference3.md} +1 -1
- package/docs/Misc-Group/{Reference4.md → nspc.Reference4.md} +1 -1
- package/docs/Misc-Group/{Reference5.md → nspc.Reference5.md} +1 -1
- package/docs/Misc-Group/{Reference6.md → nspc.Reference6.md} +1 -1
- package/docs/Misc-Group/{SampleClassWithoutModifier.md → nspc.SampleClassWithoutModifier.md} +1 -1
- package/docs/Misc-Group/{SampleRestResource.md → nspc.SampleRestResource.md} +1 -1
- package/docs/Misc-Group/{SampleRestResourceWithInnerClass.md → nspc.SampleRestResourceWithInnerClass.md} +1 -1
- package/docs/README.md +19 -19
- package/docs/Sample-Interfaces/{SampleInterface.md → nspc.SampleInterface.md} +1 -1
- package/docs/index.html +22 -22
- package/docs/{openapi.json → restapi.json} +12 -13
- package/examples/force-app/main/default/restapi/SampleRestResource.cls +0 -4
- package/examples/force-app/main/default/restapi/references/Reference2.cls +6 -0
- package/lib/cli/generate.js +12 -0
- package/lib/cli/generate.js.map +1 -1
- package/lib/model/markdown-type-file.d.ts +4 -3
- package/lib/model/markdown-type-file.js +13 -4
- package/lib/model/markdown-type-file.js.map +1 -1
- package/lib/model/openapi/open-api.d.ts +1 -1
- package/lib/model/openapi/open-api.js.map +1 -1
- package/lib/model/openapi/openapi-type-file.js +3 -2
- package/lib/model/openapi/openapi-type-file.js.map +1 -1
- package/lib/settings.d.ts +5 -0
- package/lib/settings.js +12 -0
- package/lib/settings.js.map +1 -1
- package/lib/test-helpers/DocCommentAnnotationBuilder.d.ts +2 -0
- package/lib/test-helpers/DocCommentAnnotationBuilder.js +6 -1
- package/lib/test-helpers/DocCommentAnnotationBuilder.js.map +1 -1
- package/lib/test-helpers/FieldMirrorBuilder.d.ts +3 -1
- package/lib/test-helpers/FieldMirrorBuilder.js +6 -0
- package/lib/test-helpers/FieldMirrorBuilder.js.map +1 -1
- package/lib/test-helpers/SettingsBuilder.js +1 -0
- package/lib/test-helpers/SettingsBuilder.js.map +1 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.js +2 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.js.map +1 -1
- package/lib/transpiler/openapi/open-api-docs-processor.d.ts +1 -0
- package/lib/transpiler/openapi/open-api-docs-processor.js +4 -2
- package/lib/transpiler/openapi/open-api-docs-processor.js.map +1 -1
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.d.ts +2 -0
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js +35 -5
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js.map +1 -1
- package/package.json +5 -5
- package/src/cli/generate.ts +13 -0
- package/src/model/markdown-type-file.ts +14 -4
- package/src/model/openapi/open-api.ts +1 -1
- package/src/model/openapi/openapi-type-file.ts +3 -2
- package/src/service/__tests__/apex-file-reader.spec.ts +1 -0
- package/src/settings.ts +17 -0
- package/src/test-helpers/DocCommentAnnotationBuilder.ts +7 -1
- package/src/test-helpers/FieldMirrorBuilder.ts +8 -1
- package/src/test-helpers/SettingsBuilder.ts +1 -0
- package/src/transpiler/markdown/class-file-generatorHelper.ts +2 -1
- package/src/transpiler/openapi/open-api-docs-processor.ts +4 -2
- package/src/transpiler/openapi/parsers/ReferenceBuilder.ts +41 -5
- package/src/transpiler/openapi/parsers/__tests__/ReferenceBuilder.spec.ts +85 -0
- package/docs/API/SampleClassWithoutModifier.md +0 -11
- package/docs/Main/GroupedClass.md +0 -10
- package/docs/Misc-Group/AnotherInterface.md +0 -1
- package/docs/Misc-Group/Reference2.md +0 -7
package/src/settings.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface SettingsConfig {
|
|
|
10
10
|
defaultGroupName: string;
|
|
11
11
|
sanitizeHtml: boolean;
|
|
12
12
|
openApiTitle?: string;
|
|
13
|
+
namespace?: string;
|
|
14
|
+
openApiFileName: string;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export class Settings {
|
|
@@ -63,4 +65,19 @@ export class Settings {
|
|
|
63
65
|
public getOpenApiTitle(): string | undefined {
|
|
64
66
|
return this.config.openApiTitle;
|
|
65
67
|
}
|
|
68
|
+
|
|
69
|
+
public getNamespace(): string | undefined {
|
|
70
|
+
return this.config.namespace;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
public getNamespacePrefix(): string {
|
|
74
|
+
if (!this.config.namespace) {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
return `${this.config.namespace}.`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public openApiFileName(): string {
|
|
81
|
+
return this.config.openApiFileName;
|
|
82
|
+
}
|
|
66
83
|
}
|
|
@@ -2,17 +2,23 @@ import { DocCommentAnnotation } from '@cparra/apex-reflection';
|
|
|
2
2
|
|
|
3
3
|
export class DocCommentAnnotationBuilder {
|
|
4
4
|
private name = '';
|
|
5
|
+
private bodyLines: string[] = [];
|
|
5
6
|
|
|
6
7
|
withName(name: string): DocCommentAnnotationBuilder {
|
|
7
8
|
this.name = name;
|
|
8
9
|
return this;
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
withBodyLines(bodyLines: string[]): DocCommentAnnotationBuilder {
|
|
13
|
+
this.bodyLines = bodyLines;
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
build(): DocCommentAnnotation {
|
|
12
18
|
return {
|
|
13
19
|
name: this.name,
|
|
14
20
|
body: '',
|
|
15
|
-
bodyLines:
|
|
21
|
+
bodyLines: this.bodyLines,
|
|
16
22
|
};
|
|
17
23
|
}
|
|
18
24
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { FieldMirror } from '@cparra/apex-reflection';
|
|
1
|
+
import { DocComment, FieldMirror } from '@cparra/apex-reflection';
|
|
2
2
|
import { ReferencedType } from '@cparra/apex-reflection/index';
|
|
3
3
|
|
|
4
4
|
type MemberModifier = 'static' | 'webservice' | 'final' | 'override' | 'testmethod' | 'transient';
|
|
5
5
|
|
|
6
6
|
export class FieldMirrorBuilder {
|
|
7
|
+
private docComment: DocComment | undefined = undefined;
|
|
7
8
|
private accessModifier = 'public';
|
|
8
9
|
private name = 'fieldName';
|
|
9
10
|
private memberModifiers: MemberModifier[] = [];
|
|
@@ -40,6 +41,11 @@ export class FieldMirrorBuilder {
|
|
|
40
41
|
return this;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
withDocComment(docComment: DocComment): FieldMirrorBuilder {
|
|
45
|
+
this.docComment = docComment;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
build(): FieldMirror {
|
|
44
50
|
return {
|
|
45
51
|
access_modifier: this.accessModifier,
|
|
@@ -47,6 +53,7 @@ export class FieldMirrorBuilder {
|
|
|
47
53
|
name: this.name,
|
|
48
54
|
memberModifiers: this.memberModifiers,
|
|
49
55
|
typeReference: this.type,
|
|
56
|
+
docComment: this.docComment,
|
|
50
57
|
};
|
|
51
58
|
}
|
|
52
59
|
}
|
|
@@ -11,7 +11,8 @@ export default class ClassFileGeneratorHelper {
|
|
|
11
11
|
|
|
12
12
|
public static getFileLink(classModel: Type) {
|
|
13
13
|
const directoryRoot = this.getDirectoryRoot(classModel);
|
|
14
|
-
|
|
14
|
+
const fullClassName = `${Settings.getInstance().getNamespacePrefix()}${classModel.name}`;
|
|
15
|
+
return `[${fullClassName}](${directoryRoot}${fullClassName}.md)`;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
public static getFileLinkByTypeName(typeName: string) {
|
|
@@ -18,7 +18,7 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
|
|
|
18
18
|
if (!title) {
|
|
19
19
|
throw Error('No OpenApi title was provided.');
|
|
20
20
|
}
|
|
21
|
-
this.openApiModel = new OpenApi(title, '1.0.0');
|
|
21
|
+
this.openApiModel = new OpenApi(title, '1.0.0', Settings.getInstance().getNamespace());
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
fileBuilder(): FileContainer {
|
|
@@ -57,9 +57,11 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
|
|
|
57
57
|
|
|
58
58
|
// DELETE
|
|
59
59
|
parser.parseMethod(typeAsClass, endpointPath, 'delete');
|
|
60
|
+
}
|
|
60
61
|
|
|
62
|
+
onAfterProcess: ((types: Type[]) => void) | undefined = () => {
|
|
61
63
|
this._fileContainer.pushFile(new OpenapiTypeFile(this.openApiModel));
|
|
62
|
-
}
|
|
64
|
+
};
|
|
63
65
|
|
|
64
66
|
private getEndpointPath(type: Type): string | null {
|
|
65
67
|
const restResourceAnnotation = type.annotations.find((element) => element.name.toLowerCase() === 'restresource');
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as yaml from 'js-yaml';
|
|
1
2
|
import {
|
|
2
3
|
PropertiesObject,
|
|
3
4
|
ReferenceObject,
|
|
@@ -6,8 +7,9 @@ import {
|
|
|
6
7
|
SchemaObjectObject,
|
|
7
8
|
} from '../../../model/openapi/open-api-types';
|
|
8
9
|
import { TypeBundle, TypesRepository } from '../../../model/types-repository';
|
|
9
|
-
import { ClassMirror, FieldMirror, PropertyMirror
|
|
10
|
+
import { ClassMirror, DocCommentAnnotation, FieldMirror, PropertyMirror } from '@cparra/apex-reflection';
|
|
10
11
|
import { ListObjectType, ReferencedType } from '@cparra/apex-reflection/index';
|
|
12
|
+
import { ApexDocSchemaObject } from '../../../model/openapi/apex-doc-types';
|
|
11
13
|
|
|
12
14
|
type TypeBundleWithIsCollection = TypeBundle & { isCollection: boolean };
|
|
13
15
|
|
|
@@ -64,12 +66,20 @@ export class ReferenceBuilder {
|
|
|
64
66
|
const properties: PropertiesObject = {};
|
|
65
67
|
let referencedComponents: ReferenceComponent[] = [];
|
|
66
68
|
propertiesAndFields.forEach((current) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
// Check for "@http-schema" annotations within properties themselves. If these are specified they
|
|
70
|
+
// take precedence over the property type itself.
|
|
71
|
+
const manuallyDefinedHttpSchema = current.docComment?.annotations.find(
|
|
72
|
+
(annotation) => annotation.name.toLowerCase() === 'http-schema',
|
|
73
|
+
);
|
|
74
|
+
if (manuallyDefinedHttpSchema) {
|
|
75
|
+
this.handleOverriddenSchema(manuallyDefinedHttpSchema, properties, current, referencedComponents);
|
|
76
|
+
} else {
|
|
77
|
+
const pair = this.getReferenceType(current.typeReference);
|
|
78
|
+
properties[current.name] = pair.schema;
|
|
79
|
+
pair.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
80
|
+
}
|
|
69
81
|
properties[current.name].description = current.docComment?.description;
|
|
70
|
-
pair.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
71
82
|
});
|
|
72
|
-
|
|
73
83
|
const mainReferenceComponents = this.buildMainReferenceComponent(typeBundle, properties);
|
|
74
84
|
|
|
75
85
|
// Make sure to add the "main" reference first
|
|
@@ -83,6 +93,28 @@ export class ReferenceBuilder {
|
|
|
83
93
|
};
|
|
84
94
|
}
|
|
85
95
|
|
|
96
|
+
private handleOverriddenSchema(
|
|
97
|
+
manuallyDefinedHttpSchema: DocCommentAnnotation,
|
|
98
|
+
properties: PropertiesObject,
|
|
99
|
+
current: FieldMirror | PropertyMirror,
|
|
100
|
+
referencedComponents: ReferenceComponent[],
|
|
101
|
+
) {
|
|
102
|
+
// This can be of type ApexDocSchemaObject
|
|
103
|
+
const inYaml = manuallyDefinedHttpSchema?.bodyLines.reduce((prev, current, _) => prev + '\n' + current);
|
|
104
|
+
const asJson = yaml.load(inYaml) as ApexDocSchemaObject;
|
|
105
|
+
const isReference = this.isReferenceString(asJson);
|
|
106
|
+
|
|
107
|
+
if (isReference) {
|
|
108
|
+
const reference = this.build(asJson);
|
|
109
|
+
properties[current.name] = reference.entrypointReferenceObject;
|
|
110
|
+
reference.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
111
|
+
} else {
|
|
112
|
+
// If we are dealing with a manually defined schema object, we can add it directly to the "properties" map,
|
|
113
|
+
// because we don't need to add a reference component.
|
|
114
|
+
properties[current.name] = asJson;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
86
118
|
private getReferenceName(typeBundle: TypeBundleWithIsCollection): string {
|
|
87
119
|
let referenceName = typeBundle.type.name;
|
|
88
120
|
if (typeBundle.isChild) {
|
|
@@ -180,6 +212,10 @@ export class ReferenceBuilder {
|
|
|
180
212
|
referenceComponents: [...innerReference.referenceComponents],
|
|
181
213
|
};
|
|
182
214
|
}
|
|
215
|
+
|
|
216
|
+
private isReferenceString = (targetObject: any): targetObject is string => {
|
|
217
|
+
return typeof targetObject === 'string' || targetObject instanceof String;
|
|
218
|
+
};
|
|
183
219
|
}
|
|
184
220
|
|
|
185
221
|
type SchemaObjectReferencePair = {
|
|
@@ -3,6 +3,8 @@ import { ReferenceBuilder } from '../ReferenceBuilder';
|
|
|
3
3
|
import { ClassMirrorBuilder } from '../../../../test-helpers/ClassMirrorBuilder';
|
|
4
4
|
import { FieldMirrorBuilder } from '../../../../test-helpers/FieldMirrorBuilder';
|
|
5
5
|
import { SchemaObjectArray, SchemaObjectObject } from '../../../../model/openapi/open-api-types';
|
|
6
|
+
import { DocCommentBuilder } from '../../../../test-helpers/DocCommentBuilder';
|
|
7
|
+
import { DocCommentAnnotationBuilder } from '../../../../test-helpers/DocCommentAnnotationBuilder';
|
|
6
8
|
|
|
7
9
|
describe('ReferenceBuilder', () => {
|
|
8
10
|
describe('Validation', () => {
|
|
@@ -619,4 +621,87 @@ describe('ReferenceBuilder', () => {
|
|
|
619
621
|
expect((result.referenceComponents[1].schema as SchemaObjectObject).properties).toHaveProperty('fieldName');
|
|
620
622
|
});
|
|
621
623
|
});
|
|
624
|
+
|
|
625
|
+
describe('References can override their type', () => {
|
|
626
|
+
it("should correctly parse a manually defined schema in the reference's ApexDoc", function () {
|
|
627
|
+
const classMirror = new ClassMirrorBuilder()
|
|
628
|
+
.addFiled(
|
|
629
|
+
new FieldMirrorBuilder()
|
|
630
|
+
.withName('fieldName')
|
|
631
|
+
.withType('Object')
|
|
632
|
+
.withDocComment(
|
|
633
|
+
new DocCommentBuilder()
|
|
634
|
+
.addAnnotation(
|
|
635
|
+
new DocCommentAnnotationBuilder().withName('http-schema').withBodyLines(['type: string']).build(),
|
|
636
|
+
)
|
|
637
|
+
.build(),
|
|
638
|
+
)
|
|
639
|
+
.build(),
|
|
640
|
+
)
|
|
641
|
+
.build();
|
|
642
|
+
|
|
643
|
+
TypesRepository.getInstance = jest.fn().mockReturnValue({
|
|
644
|
+
getFromAllByName: jest.fn().mockReturnValue({ type: classMirror, isChild: false }),
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
const result = new ReferenceBuilder().build('className');
|
|
648
|
+
|
|
649
|
+
const schema = result.referenceComponents[0].schema as SchemaObjectObject;
|
|
650
|
+
expect(schema.properties).toHaveProperty('fieldName');
|
|
651
|
+
const fieldSchema = schema.properties!['fieldName'] as SchemaObjectObject;
|
|
652
|
+
expect(fieldSchema.type).toBe('string');
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
it('should correctly parse a manually defined reference while parsing properties', function () {
|
|
656
|
+
const mainClassMirror = new ClassMirrorBuilder()
|
|
657
|
+
.withName('parent')
|
|
658
|
+
.addFiled(
|
|
659
|
+
new FieldMirrorBuilder()
|
|
660
|
+
.withName('childClassMember')
|
|
661
|
+
.withType('Object')
|
|
662
|
+
.withDocComment(
|
|
663
|
+
new DocCommentBuilder()
|
|
664
|
+
.addAnnotation(
|
|
665
|
+
new DocCommentAnnotationBuilder().withName('http-schema').withBodyLines(['ChildClass']).build(),
|
|
666
|
+
)
|
|
667
|
+
.build(),
|
|
668
|
+
)
|
|
669
|
+
.build(),
|
|
670
|
+
)
|
|
671
|
+
.build();
|
|
672
|
+
|
|
673
|
+
const childClass = new ClassMirrorBuilder()
|
|
674
|
+
.withName('child')
|
|
675
|
+
.addFiled(
|
|
676
|
+
new FieldMirrorBuilder()
|
|
677
|
+
.withName('grandChildClassMember')
|
|
678
|
+
.withReferencedType({
|
|
679
|
+
type: 'GrandChildClass',
|
|
680
|
+
rawDeclaration: 'GrandChildClass',
|
|
681
|
+
})
|
|
682
|
+
.build(),
|
|
683
|
+
)
|
|
684
|
+
.build();
|
|
685
|
+
|
|
686
|
+
const grandChildClass = new ClassMirrorBuilder()
|
|
687
|
+
.withName('grandchild')
|
|
688
|
+
.addFiled(new FieldMirrorBuilder().withName('stringMember').withType('String').build())
|
|
689
|
+
.build();
|
|
690
|
+
|
|
691
|
+
TypesRepository.getInstance = jest.fn().mockReturnValue({
|
|
692
|
+
getFromAllByName: jest
|
|
693
|
+
.fn()
|
|
694
|
+
.mockReturnValueOnce({ type: mainClassMirror, isChild: false })
|
|
695
|
+
.mockReturnValueOnce({ type: childClass, isChild: false })
|
|
696
|
+
.mockReturnValueOnce({ type: grandChildClass, isChild: false }),
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
const result = new ReferenceBuilder().build('className');
|
|
700
|
+
|
|
701
|
+
expect(result.referenceComponents).toHaveLength(3);
|
|
702
|
+
expect(result.referenceComponents.some((ref) => ref.referencedClass === 'parent')).toBe(true);
|
|
703
|
+
expect(result.referenceComponents.some((ref) => ref.referencedClass === 'child')).toBe(true);
|
|
704
|
+
expect(result.referenceComponents.some((ref) => ref.referencedClass === 'grandchild')).toBe(true);
|
|
705
|
+
});
|
|
706
|
+
});
|
|
622
707
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# AnotherInterface
|