@cparra/apexdocs 3.0.0-rc.0 → 3.0.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 +50 -571
- package/dist/cli/generate.js +73 -3094
- package/dist/defaults-BcE8DTat.js +13 -0
- package/dist/defaults-D07y_bq4.js +40 -0
- package/dist/defaults-gPzwP66p.js +14 -0
- package/dist/index.d.ts +35 -3
- package/dist/index.js +90 -2
- package/dist/logger-BEbUIfqN.js +3282 -0
- package/dist/logger-BGuf1PnL.js +3281 -0
- package/dist/logger-CWBRF2za.js +3284 -0
- package/dist/logger-CdBmDEN1.js +3283 -0
- package/dist/logger-Ce4QqPFR.js +3278 -0
- package/dist/logger-CyEVYaAC.js +3284 -0
- package/dist/logger-D7a83ycP.js +3277 -0
- package/dist/logger-DGaHeBKk.js +3279 -0
- package/dist/logger-Dqhl_lO_.js +3278 -0
- package/dist/logger-aySSWi0G.js +3280 -0
- package/dist/logger-qLCcAtiy.js +3284 -0
- package/examples/README.md +5 -0
- package/examples/docsify/README.md +17 -0
- package/examples/docsify/apexdocs.config.ts +13 -0
- package/examples/docsify/classes/ASampleClass.cls +57 -0
- package/examples/docsify/classes/CodeControl.cls +19 -0
- package/examples/docsify/classes/SampleClass.cls +95 -0
- package/examples/docsify/classes/SampleInterface.cls +17 -0
- package/examples/docsify/classes/SomeDto.cls +122 -0
- package/examples/docsify/docs/.nojekyll +0 -0
- package/examples/docsify/docs/README.md +25 -0
- package/examples/docsify/docs/_config.yml +1 -0
- package/examples/docsify/docs/index.html +22 -0
- package/examples/docsify/docs/miscellaneous/ASampleClass.md +88 -0
- package/examples/docsify/docs/miscellaneous/CodeControl.md +107 -0
- package/examples/docsify/docs/miscellaneous/SomeDto.md +244 -0
- package/examples/docsify/docs/sample-classes/SampleClass.md +171 -0
- package/examples/docsify/docs/sample-interfaces/SampleInterface.md +36 -0
- package/examples/docsify/package-lock.json +2459 -0
- package/examples/docsify/package.json +14 -0
- package/examples/imported/.forceignore +12 -0
- package/examples/imported/README.md +6 -0
- package/examples/imported/config/project-scratch-def.json +5 -0
- package/examples/imported/docs/index.md +109 -0
- package/examples/imported/docs/miscellaneous/BaseClass.md +13 -0
- package/examples/imported/docs/miscellaneous/MultiInheritanceClass.md +69 -0
- package/examples/imported/docs/miscellaneous/ParentInterface.md +12 -0
- package/examples/imported/docs/miscellaneous/ReferencedEnum.md +5 -0
- package/examples/imported/docs/miscellaneous/SampleException.md +21 -0
- package/examples/imported/docs/miscellaneous/SampleInterface.md +113 -0
- package/examples/imported/docs/miscellaneous/Url.md +308 -0
- package/examples/imported/docs/sample-enums/SampleEnum.md +33 -0
- package/examples/imported/docs/samplegroup/SampleClass.md +167 -0
- package/examples/imported/force-app/classes/BaseClass.cls +3 -0
- package/examples/imported/force-app/classes/MultiInheritanceClass.cls +1 -0
- package/examples/imported/force-app/classes/ParentInterface.cls +3 -0
- package/examples/imported/force-app/classes/ReferencedEnum.cls +3 -0
- package/examples/imported/force-app/classes/SampleClass.cls +72 -0
- package/examples/imported/force-app/classes/SampleInterface.cls +50 -0
- package/examples/imported/force-app/classes/Url.cls +196 -0
- package/examples/imported/package-lock.json +665 -0
- package/examples/imported/package.json +6 -0
- package/examples/imported/scripts/process-docs.mjs +16 -0
- package/examples/imported/sfdx-project.json +12 -0
- package/examples/markdown/README.md +7 -0
- package/examples/markdown-jsconfig/README.md +9 -0
- package/examples/markdown-jsconfig/apexdocs.config.mjs +1 -0
- package/examples/markdown-jsconfig/docs/index.md +1 -1
- package/examples/open-api/README.md +5 -0
- package/examples/open-api/docs/openapi.json +2 -570
- package/examples/vitepress/README.md +25 -0
- package/examples/vitepress/apexdocs.config.ts +2 -0
- package/examples/vitepress/force-app/main/default/classes/{SampleClass.cls → feature-a/SampleClass.cls} +1 -0
- package/examples/vitepress/force-app/main/default/classes/feature-a/SampleEnum.cls +30 -0
- package/examples/vitepress/force-app/main/default/classes/feature-a/SampleException.cls +17 -0
- package/package.json +2 -2
- package/src/application/Apexdocs.ts +16 -19
- package/src/application/__tests__/apex-file-reader.spec.ts +108 -67
- package/src/application/apex-file-reader.ts +1 -0
- package/src/application/generators/openapi.ts +17 -13
- package/src/cli/args.ts +12 -3
- package/src/cli/commands/markdown.ts +14 -9
- package/src/cli/commands/openapi.ts +5 -5
- package/src/cli/generate.ts +20 -4
- package/src/core/markdown/__test__/generating-class-docs.spec.ts +14 -257
- package/src/core/markdown/__test__/generating-docs.spec.ts +271 -4
- package/src/core/markdown/__test__/generating-enum-docs.spec.ts +4 -264
- package/src/core/markdown/__test__/generating-interface-docs.spec.ts +4 -232
- package/src/core/markdown/__test__/generating-reference-guide.spec.ts +17 -1
- package/src/core/markdown/__test__/test-helpers.ts +3 -1
- package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +3 -1
- package/src/core/markdown/adapters/renderable-to-page-data.ts +6 -4
- package/src/core/markdown/generate-docs.ts +13 -15
- package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +2 -18
- package/src/core/markdown/reflection/__test__/helpers.ts +18 -0
- package/src/core/markdown/reflection/__test__/remove-excluded-tags.spec.ts +200 -0
- package/src/core/markdown/reflection/remove-excluded-tags.ts +168 -0
- package/src/core/markdown/reflection/{sort-members.ts → sort-types-and-members.ts} +7 -5
- package/src/core/markdown/templates/reference-guide.ts +2 -2
- package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +6 -3
- package/src/core/openapi/open-api-docs-processor.ts +3 -3
- package/src/core/openapi/parser.ts +5 -2
- package/src/core/shared/types.d.ts +4 -2
- package/src/defaults.ts +15 -3
- package/src/index.ts +65 -4
- package/src/util/error-logger.ts +36 -36
- package/src/util/logger.ts +18 -11
- /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleEnum.cls +0 -0
- /package/examples/{vitepress/force-app/main/default → imported/force-app}/classes/SampleException.cls +0 -0
- /package/examples/vitepress/force-app/main/default/classes/{SampleInterface.cls → feature-a/SampleInterface.cls} +0 -0
|
@@ -26,24 +26,16 @@ import { convertToDocumentationBundle } from './adapters/renderable-to-page-data
|
|
|
26
26
|
import { filterScope } from './reflection/filter-scope';
|
|
27
27
|
import { Template } from './templates/template';
|
|
28
28
|
import { hookableTemplate } from './templates/hookable';
|
|
29
|
-
import {
|
|
29
|
+
import { sortTypesAndMembers } from './reflection/sort-types-and-members';
|
|
30
30
|
import { isSkip } from '../shared/utils';
|
|
31
31
|
import { parsedFilesToReferenceGuide } from './adapters/reference-guide';
|
|
32
|
+
import { removeExcludedTags } from './reflection/remove-excluded-tags';
|
|
32
33
|
|
|
33
|
-
export type MarkdownGeneratorConfig =
|
|
34
|
+
export type MarkdownGeneratorConfig = Omit<
|
|
34
35
|
UserDefinedMarkdownConfig,
|
|
35
|
-
| '
|
|
36
|
-
| 'scope'
|
|
37
|
-
| 'namespace'
|
|
38
|
-
| 'defaultGroupName'
|
|
39
|
-
| 'transformReferenceGuide'
|
|
40
|
-
| 'transformDocs'
|
|
41
|
-
| 'transformDocPage'
|
|
42
|
-
| 'transformReference'
|
|
43
|
-
| 'linkingStrategy'
|
|
36
|
+
'sourceDir' | 'targetGenerator' | 'includeMetadata'
|
|
44
37
|
> & {
|
|
45
38
|
referenceGuideTemplate: string;
|
|
46
|
-
sortMembersAlphabetically: boolean;
|
|
47
39
|
};
|
|
48
40
|
|
|
49
41
|
export class HookError {
|
|
@@ -56,8 +48,13 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config: Markdown
|
|
|
56
48
|
const filterOutOfScope = apply(filterScope, config.scope);
|
|
57
49
|
const convertToReferences = apply(parsedFilesToReferenceGuide, config);
|
|
58
50
|
const convertToRenderableBundle = apply(parsedFilesToRenderableBundle, config);
|
|
59
|
-
const convertToDocumentationBundleForTemplate = apply(
|
|
60
|
-
|
|
51
|
+
const convertToDocumentationBundleForTemplate = apply(
|
|
52
|
+
convertToDocumentationBundle,
|
|
53
|
+
config.referenceGuideTitle,
|
|
54
|
+
config.referenceGuideTemplate,
|
|
55
|
+
);
|
|
56
|
+
const sort = apply(sortTypesAndMembers, config.sortAlphabetically);
|
|
57
|
+
const removeExcluded = apply(removeExcludedTags, config.excludeTags);
|
|
61
58
|
|
|
62
59
|
return pipe(
|
|
63
60
|
apexBundles,
|
|
@@ -65,7 +62,8 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config: Markdown
|
|
|
65
62
|
TE.map(filterOutOfScope),
|
|
66
63
|
TE.map(addInheritedMembersToTypes),
|
|
67
64
|
TE.map(addInheritanceChainToTypes),
|
|
68
|
-
TE.map(
|
|
65
|
+
TE.map(sort),
|
|
66
|
+
TE.map(removeExcluded),
|
|
69
67
|
TE.bindTo('parsedFiles'),
|
|
70
68
|
TE.bind('references', ({ parsedFiles }) => TE.right(convertToReferences(parsedFiles))),
|
|
71
69
|
TE.flatMap(({ parsedFiles, references }) => transformReferenceHook(config)({ references, parsedFiles })),
|
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ClassMirror, EnumMirror, InterfaceMirror, reflect } from '@cparra/apex-reflection';
|
|
1
|
+
import { ClassMirror, EnumMirror, InterfaceMirror } from '@cparra/apex-reflection';
|
|
3
2
|
import { filterScope } from '../filter-scope';
|
|
4
|
-
|
|
5
|
-
function parsedFileFromRawString(raw: string): ParsedFile {
|
|
6
|
-
const { error, typeMirror } = reflect(raw);
|
|
7
|
-
if (error) {
|
|
8
|
-
throw new Error(error.message);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
return {
|
|
12
|
-
source: {
|
|
13
|
-
filePath: 'test.cls',
|
|
14
|
-
name: typeMirror!.name,
|
|
15
|
-
type: typeMirror!.type_name,
|
|
16
|
-
},
|
|
17
|
-
type: typeMirror!,
|
|
18
|
-
};
|
|
19
|
-
}
|
|
3
|
+
import { parsedFileFromRawString } from './helpers';
|
|
20
4
|
|
|
21
5
|
describe('When filtering scope', () => {
|
|
22
6
|
it('filters out files with the @ignore annotation', () => {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ParsedFile } from '../../../shared/types';
|
|
2
|
+
import { reflect } from '@cparra/apex-reflection';
|
|
3
|
+
|
|
4
|
+
export function parsedFileFromRawString(raw: string): ParsedFile {
|
|
5
|
+
const { error, typeMirror } = reflect(raw);
|
|
6
|
+
if (error) {
|
|
7
|
+
throw new Error(error.message);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
source: {
|
|
12
|
+
filePath: 'test.cls',
|
|
13
|
+
name: typeMirror!.name,
|
|
14
|
+
type: typeMirror!.type_name,
|
|
15
|
+
},
|
|
16
|
+
type: typeMirror!,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { parsedFileFromRawString } from './helpers';
|
|
2
|
+
import { removeExcludedTags } from '../remove-excluded-tags';
|
|
3
|
+
import { ClassMirror, InterfaceMirror } from '@cparra/apex-reflection';
|
|
4
|
+
|
|
5
|
+
describe('when removing excluded tags', () => {
|
|
6
|
+
describe('from any type', () => {
|
|
7
|
+
it('removes annotations', () => {
|
|
8
|
+
const tagsToExclude = ['group'];
|
|
9
|
+
const content = `
|
|
10
|
+
/**
|
|
11
|
+
* @group MyGroup
|
|
12
|
+
* @custom myCustomTag
|
|
13
|
+
*/
|
|
14
|
+
global class MyClass {}
|
|
15
|
+
`;
|
|
16
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
17
|
+
|
|
18
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
19
|
+
|
|
20
|
+
expect(result[0].type.docComment?.annotations).toHaveLength(1);
|
|
21
|
+
expect(result[0].type.docComment?.annotations[0].name).toBe('custom');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('removes example annotations', () => {
|
|
25
|
+
const tagsToExclude = ['example'];
|
|
26
|
+
const content = `
|
|
27
|
+
/**
|
|
28
|
+
* @example
|
|
29
|
+
* This is my example
|
|
30
|
+
* public void myMethod() {}
|
|
31
|
+
*/
|
|
32
|
+
global class MyClass {}
|
|
33
|
+
`;
|
|
34
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
35
|
+
|
|
36
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
37
|
+
|
|
38
|
+
expect(result[0].type.docComment?.exampleAnnotation).toBeNull();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('removes params annotations', () => {
|
|
42
|
+
const tagsToExclude = ['param'];
|
|
43
|
+
const content = `
|
|
44
|
+
/**
|
|
45
|
+
* @param myParam
|
|
46
|
+
* public void myMethod() {}
|
|
47
|
+
*/
|
|
48
|
+
global class MyClass {}
|
|
49
|
+
`;
|
|
50
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
51
|
+
|
|
52
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
53
|
+
|
|
54
|
+
expect(result[0].type.docComment?.paramAnnotations).toHaveLength(0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('removes the return annotation', () => {
|
|
58
|
+
const tagsToExclude = ['return'];
|
|
59
|
+
const content = `
|
|
60
|
+
/**
|
|
61
|
+
* @return myReturn
|
|
62
|
+
* public void myMethod() {}
|
|
63
|
+
*/
|
|
64
|
+
global class MyClass {}
|
|
65
|
+
`;
|
|
66
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
67
|
+
|
|
68
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
69
|
+
|
|
70
|
+
expect(result[0].type.docComment?.returnAnnotation).toBeNull();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('removes the throws annotations', () => {
|
|
74
|
+
const tagsToExclude = ['throws'];
|
|
75
|
+
const content = `
|
|
76
|
+
/**
|
|
77
|
+
* @throws MyException
|
|
78
|
+
* public void myMethod() {}
|
|
79
|
+
*/
|
|
80
|
+
global class MyClass {}
|
|
81
|
+
`;
|
|
82
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
83
|
+
|
|
84
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
85
|
+
|
|
86
|
+
expect(result[0].type.docComment?.throwsAnnotations).toHaveLength(0);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('removes the exception annotations', () => {
|
|
90
|
+
const tagsToExclude = ['exception'];
|
|
91
|
+
const content = `
|
|
92
|
+
/**
|
|
93
|
+
* @exception MyException
|
|
94
|
+
* public void myMethod() {}
|
|
95
|
+
*/
|
|
96
|
+
global class MyClass {}
|
|
97
|
+
`;
|
|
98
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
99
|
+
|
|
100
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
101
|
+
|
|
102
|
+
expect(result[0].type.docComment?.throwsAnnotations).toHaveLength(0);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('removes descriptions', () => {
|
|
106
|
+
const tagsToExclude = ['description'];
|
|
107
|
+
const content = `
|
|
108
|
+
/**
|
|
109
|
+
* @description This is my description
|
|
110
|
+
* public void myMethod() {}
|
|
111
|
+
*/
|
|
112
|
+
global class MyClass {}
|
|
113
|
+
`;
|
|
114
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
115
|
+
|
|
116
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
117
|
+
|
|
118
|
+
expect(result[0].type.docComment?.description).toBe('');
|
|
119
|
+
expect(result[0].type.docComment?.descriptionLines).toHaveLength(0);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('from an interface', () => {
|
|
124
|
+
it('removes annotations from methods', () => {
|
|
125
|
+
const tagsToExclude = ['throws'];
|
|
126
|
+
const content = `
|
|
127
|
+
global interface MyInterface {
|
|
128
|
+
/**
|
|
129
|
+
* @throws MyException
|
|
130
|
+
*/
|
|
131
|
+
void myMethod();
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
135
|
+
|
|
136
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
137
|
+
|
|
138
|
+
expect((result[0].type as InterfaceMirror).methods[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('from a class', () => {
|
|
143
|
+
it('removes annotations from members', () => {
|
|
144
|
+
const tagsToExclude = ['throws'];
|
|
145
|
+
const content = `
|
|
146
|
+
global class MyClass {
|
|
147
|
+
/**
|
|
148
|
+
* @throws MyException
|
|
149
|
+
*/
|
|
150
|
+
String myProperty {get; set;}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @throws MyException
|
|
154
|
+
*/
|
|
155
|
+
String myField;
|
|
156
|
+
/**
|
|
157
|
+
* @throws MyException
|
|
158
|
+
*/
|
|
159
|
+
void myMethod() {}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @throws MyException
|
|
163
|
+
*/
|
|
164
|
+
MyClass() {}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @throws MyException
|
|
168
|
+
*/
|
|
169
|
+
public enum MyEnum {}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @throws MyException
|
|
173
|
+
*/
|
|
174
|
+
interface MyInnerInterface {}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @throws MyException
|
|
178
|
+
*/
|
|
179
|
+
class MyInnerClass {}
|
|
180
|
+
}
|
|
181
|
+
`;
|
|
182
|
+
const parsedFile = parsedFileFromRawString(content);
|
|
183
|
+
|
|
184
|
+
const result = removeExcludedTags(tagsToExclude, [parsedFile]);
|
|
185
|
+
|
|
186
|
+
const classMirror = result[0].type as ClassMirror;
|
|
187
|
+
expect(classMirror.methods[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
188
|
+
expect(classMirror.properties[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
189
|
+
expect(classMirror.fields[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
190
|
+
expect(classMirror.constructors[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
191
|
+
expect(classMirror.enums[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
192
|
+
expect(classMirror.interfaces[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
193
|
+
expect(classMirror.classes[0].docComment?.throwsAnnotations).toHaveLength(0);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// fields
|
|
199
|
+
// inner interfaces
|
|
200
|
+
// inner classes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as O from 'fp-ts/Option';
|
|
2
|
+
import { match } from 'fp-ts/boolean';
|
|
3
|
+
import { ParsedFile } from '../../shared/types';
|
|
4
|
+
import { ClassMirror, DocComment, InterfaceMirror, Type } from '@cparra/apex-reflection';
|
|
5
|
+
import { pipe } from 'fp-ts/function';
|
|
6
|
+
import { apply } from '#utils/fp';
|
|
7
|
+
|
|
8
|
+
type AppliedRemoveTagFn = (tagName: string, removeFn: RemoveTagFn) => DocComment;
|
|
9
|
+
type RemoveTagFn = (docComment: DocComment) => DocComment;
|
|
10
|
+
type Documentable = { docComment?: DocComment };
|
|
11
|
+
|
|
12
|
+
export const removeExcludedTags = (excludedTags: string[], parsedFiles: ParsedFile[]): ParsedFile[] => {
|
|
13
|
+
return parsedFiles.map((parsedFile) => {
|
|
14
|
+
return {
|
|
15
|
+
...parsedFile,
|
|
16
|
+
type: removeExcludedTagsFromType(excludedTags, parsedFile.type),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const removeExcludedTagsFromType = <T extends Type>(excludedTags: string[], type: T): T => {
|
|
22
|
+
return {
|
|
23
|
+
...handleType(excludedTags, type),
|
|
24
|
+
docComment: removeExcludedTagsFromDocComment(excludedTags, type.docComment),
|
|
25
|
+
} as T;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const handleType = (excludedTags: string[], type: Type): Type => {
|
|
29
|
+
switch (type.type_name) {
|
|
30
|
+
case 'class':
|
|
31
|
+
return handleClass(excludedTags, type as ClassMirror);
|
|
32
|
+
case 'interface':
|
|
33
|
+
return handleInterface(excludedTags, type as InterfaceMirror);
|
|
34
|
+
case 'enum':
|
|
35
|
+
return type;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const handleClass = (excludedTags: string[], classMirror: ClassMirror): ClassMirror => {
|
|
40
|
+
return {
|
|
41
|
+
...classMirror,
|
|
42
|
+
methods: classMirror.methods.map((method) => removeExcludedTagsFromDocumentable(excludedTags, method)),
|
|
43
|
+
properties: classMirror.properties.map((property) => removeExcludedTagsFromDocumentable(excludedTags, property)),
|
|
44
|
+
fields: classMirror.fields.map((field) => removeExcludedTagsFromDocumentable(excludedTags, field)),
|
|
45
|
+
constructors: classMirror.constructors.map((constructor) =>
|
|
46
|
+
removeExcludedTagsFromDocumentable(excludedTags, constructor),
|
|
47
|
+
),
|
|
48
|
+
enums: classMirror.enums.map((enumType) => removeExcludedTagsFromType(excludedTags, enumType)),
|
|
49
|
+
interfaces: classMirror.interfaces.map((interfaceType) => removeExcludedTagsFromType(excludedTags, interfaceType)),
|
|
50
|
+
classes: classMirror.classes.map((innerClass) => removeExcludedTagsFromType(excludedTags, innerClass)),
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const handleInterface = (excludedTags: string[], interfaceMirror: InterfaceMirror): InterfaceMirror => {
|
|
55
|
+
return {
|
|
56
|
+
...interfaceMirror,
|
|
57
|
+
methods: interfaceMirror.methods.map((method) => removeExcludedTagsFromDocumentable(excludedTags, method)),
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const removeExcludedTagsFromDocumentable = <T extends Documentable>(excludedTags: string[], documentable: T): T => {
|
|
62
|
+
return {
|
|
63
|
+
...documentable,
|
|
64
|
+
docComment: removeExcludedTagsFromDocComment(excludedTags, documentable.docComment),
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const removeExcludedTagsFromDocComment = (
|
|
69
|
+
excludedTags: string[],
|
|
70
|
+
docComment: DocComment | undefined,
|
|
71
|
+
): DocComment | undefined => {
|
|
72
|
+
const removerFn = apply(remove, excludedTags);
|
|
73
|
+
|
|
74
|
+
return pipe(
|
|
75
|
+
O.fromNullable(docComment),
|
|
76
|
+
O.map((docComment) => removeExcludedTagsFromAnnotations(excludedTags, docComment)),
|
|
77
|
+
O.map((docComment) => removeExampleTag(apply(removerFn, docComment))),
|
|
78
|
+
O.map((docComment) => removeParamTags(apply(removerFn, docComment))),
|
|
79
|
+
O.map((docComment) => removeReturnTag(apply(removerFn, docComment))),
|
|
80
|
+
O.map((docComment) => removeThrowsTag(apply(removerFn, docComment))),
|
|
81
|
+
O.map((docComment) => removeExceptionTag(apply(removerFn, docComment))),
|
|
82
|
+
O.map((docComment) => removeDescription(apply(removerFn, docComment))),
|
|
83
|
+
O.fold(
|
|
84
|
+
() => undefined,
|
|
85
|
+
(updatedDocComment) => updatedDocComment,
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const removeExcludedTagsFromAnnotations = (excludedTags: string[], docComment: DocComment): DocComment => {
|
|
91
|
+
return pipe(
|
|
92
|
+
O.some(docComment.annotations),
|
|
93
|
+
O.map((annotations) => annotations.filter((annotation) => !includesIgnoreCase(excludedTags, annotation.name))),
|
|
94
|
+
O.fold(
|
|
95
|
+
() => docComment,
|
|
96
|
+
(filteredAnnotations) => ({
|
|
97
|
+
...docComment,
|
|
98
|
+
annotations: filteredAnnotations,
|
|
99
|
+
}),
|
|
100
|
+
),
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const removeExampleTag = (remover: AppliedRemoveTagFn): DocComment => {
|
|
105
|
+
return remover('example', (docComment) => {
|
|
106
|
+
return {
|
|
107
|
+
...docComment,
|
|
108
|
+
exampleAnnotation: null,
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const removeParamTags = (remover: AppliedRemoveTagFn): DocComment => {
|
|
114
|
+
return remover('param', (docComment) => {
|
|
115
|
+
return {
|
|
116
|
+
...docComment,
|
|
117
|
+
paramAnnotations: [],
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const removeReturnTag = (remover: AppliedRemoveTagFn): DocComment => {
|
|
123
|
+
return remover('return', (docComment) => {
|
|
124
|
+
return {
|
|
125
|
+
...docComment,
|
|
126
|
+
returnAnnotation: null,
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const removeThrowsTag = (remover: AppliedRemoveTagFn): DocComment => {
|
|
132
|
+
return remover('throws', (docComment) => {
|
|
133
|
+
return {
|
|
134
|
+
...docComment,
|
|
135
|
+
throwsAnnotations: [],
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const removeExceptionTag = (remover: AppliedRemoveTagFn): DocComment => {
|
|
141
|
+
return remover('exception', (docComment) => {
|
|
142
|
+
return {
|
|
143
|
+
...docComment,
|
|
144
|
+
throwsAnnotations: [],
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const removeDescription = (remover: AppliedRemoveTagFn): DocComment => {
|
|
150
|
+
return remover('description', (docComment) => {
|
|
151
|
+
return {
|
|
152
|
+
...docComment,
|
|
153
|
+
description: '',
|
|
154
|
+
descriptionLines: [],
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const remove = (excludedTags: string[], docComment: DocComment, tagName: string, removeFn: RemoveTagFn): DocComment => {
|
|
160
|
+
return match(
|
|
161
|
+
() => docComment,
|
|
162
|
+
() => removeFn(docComment!),
|
|
163
|
+
)(includesIgnoreCase(excludedTags, tagName) && !!docComment);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const includesIgnoreCase = (excluded: string[], value: string): boolean => {
|
|
167
|
+
return excluded.some((element) => element.toLowerCase() === value.toLowerCase());
|
|
168
|
+
};
|
|
@@ -3,11 +3,13 @@ import { ParsedFile } from '../../shared/types';
|
|
|
3
3
|
|
|
4
4
|
type Named = { name: string };
|
|
5
5
|
|
|
6
|
-
export function
|
|
7
|
-
return parsedFiles
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
export function sortTypesAndMembers(shouldSort: boolean, parsedFiles: ParsedFile[]): ParsedFile[] {
|
|
7
|
+
return parsedFiles
|
|
8
|
+
.map((parsedFile) => ({
|
|
9
|
+
...parsedFile,
|
|
10
|
+
type: sortTypeMember(parsedFile.type, shouldSort),
|
|
11
|
+
}))
|
|
12
|
+
.sort((a, b) => sortByNames(shouldSort, a.type, b.type));
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
function sortByNames<T extends Named>(shouldSort: boolean, a: T, b: T): number {
|
|
@@ -4,6 +4,9 @@ import { SettingsBuilder } from '../../../test-helpers/SettingsBuilder';
|
|
|
4
4
|
import { DocCommentBuilder } from '../../../test-helpers/DocCommentBuilder';
|
|
5
5
|
import { AnnotationBuilder } from '../../../test-helpers/AnnotationBuilder';
|
|
6
6
|
import { ClassMirrorBuilder } from '../../../test-helpers/ClassMirrorBuilder';
|
|
7
|
+
import { NoLogger } from '../../../util/logger';
|
|
8
|
+
|
|
9
|
+
const noLogger = new NoLogger();
|
|
7
10
|
|
|
8
11
|
beforeEach(() => {
|
|
9
12
|
OpenApiSettings.build(new SettingsBuilder().build());
|
|
@@ -18,7 +21,7 @@ it('should add a path based on the @UrlResource annotation on the class', functi
|
|
|
18
21
|
.addAnnotation(new AnnotationBuilder().addElementValue(annotationElementValue).build())
|
|
19
22
|
.build();
|
|
20
23
|
|
|
21
|
-
const processor = new OpenApiDocsProcessor();
|
|
24
|
+
const processor = new OpenApiDocsProcessor(noLogger);
|
|
22
25
|
processor.onProcess(classMirror);
|
|
23
26
|
|
|
24
27
|
expect(processor.openApiModel.paths).toHaveProperty('Account/');
|
|
@@ -33,7 +36,7 @@ it('should respect slashes', function () {
|
|
|
33
36
|
.addAnnotation(new AnnotationBuilder().addElementValue(annotationElementValue).build())
|
|
34
37
|
.build();
|
|
35
38
|
|
|
36
|
-
const processor = new OpenApiDocsProcessor();
|
|
39
|
+
const processor = new OpenApiDocsProcessor(noLogger);
|
|
37
40
|
processor.onProcess(classMirror);
|
|
38
41
|
|
|
39
42
|
expect(processor.openApiModel.paths).toHaveProperty('v1/Account/');
|
|
@@ -49,7 +52,7 @@ it('should contain a path with a description when the class has an ApexDoc comme
|
|
|
49
52
|
.withDocComment(new DocCommentBuilder().withDescription('My Description').build())
|
|
50
53
|
.build();
|
|
51
54
|
|
|
52
|
-
const processor = new OpenApiDocsProcessor();
|
|
55
|
+
const processor = new OpenApiDocsProcessor(noLogger);
|
|
53
56
|
processor.onProcess(classMirror);
|
|
54
57
|
|
|
55
58
|
expect(processor.openApiModel.paths['Account/'].description).toBe('My Description');
|
|
@@ -11,7 +11,7 @@ export class OpenApiDocsProcessor {
|
|
|
11
11
|
protected readonly _fileContainer: FileContainer;
|
|
12
12
|
openApiModel: OpenApi;
|
|
13
13
|
|
|
14
|
-
constructor() {
|
|
14
|
+
constructor(private logger: Logger) {
|
|
15
15
|
this._fileContainer = new FileContainer();
|
|
16
16
|
const title = OpenApiSettings.getInstance().getOpenApiTitle();
|
|
17
17
|
if (!title) {
|
|
@@ -29,7 +29,7 @@ export class OpenApiDocsProcessor {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
onProcess(type: Type): void {
|
|
32
|
-
|
|
32
|
+
this.logger.logSingle(`Processing ${type.name}`, 'green');
|
|
33
33
|
|
|
34
34
|
const endpointPath = this.getEndpointPath(type);
|
|
35
35
|
if (!endpointPath) {
|
|
@@ -80,7 +80,7 @@ export class OpenApiDocsProcessor {
|
|
|
80
80
|
(element) => element.key.toLowerCase() === 'urlmapping',
|
|
81
81
|
);
|
|
82
82
|
if (!urlMapping) {
|
|
83
|
-
|
|
83
|
+
this.logger.error(`Type does not contain urlMapping annotation ${type.name}`);
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -9,12 +9,15 @@ export interface TypeParser {
|
|
|
9
9
|
type NameAware = { name: string };
|
|
10
10
|
|
|
11
11
|
export class RawBodyParser implements TypeParser {
|
|
12
|
-
constructor(
|
|
12
|
+
constructor(
|
|
13
|
+
private logger: Logger,
|
|
14
|
+
public typeBundles: UnparsedSourceFile[],
|
|
15
|
+
) {}
|
|
13
16
|
|
|
14
17
|
parse(reflect: (apexBundle: UnparsedSourceFile) => ReflectionResult): Type[] {
|
|
15
18
|
const types = this.typeBundles
|
|
16
19
|
.map((currentBundle) => {
|
|
17
|
-
|
|
20
|
+
this.logger.log(`Parsing file: ${currentBundle.filePath}`);
|
|
18
21
|
return reflect(currentBundle);
|
|
19
22
|
})
|
|
20
23
|
.filter((reflectionResult) => {
|
|
@@ -16,11 +16,13 @@ export type UserDefinedMarkdownConfig = {
|
|
|
16
16
|
targetGenerator: 'markdown';
|
|
17
17
|
targetDir: string;
|
|
18
18
|
scope: string[];
|
|
19
|
-
defaultGroupName: string;
|
|
20
19
|
namespace?: string;
|
|
21
|
-
|
|
20
|
+
defaultGroupName: string;
|
|
21
|
+
sortAlphabetically: boolean;
|
|
22
22
|
includeMetadata: boolean;
|
|
23
23
|
linkingStrategy: LinkingStrategy;
|
|
24
|
+
excludeTags: string[];
|
|
25
|
+
referenceGuideTitle: string;
|
|
24
26
|
} & Partial<ConfigurableHooks>;
|
|
25
27
|
|
|
26
28
|
export type UserDefinedOpenApiConfig = {
|
package/src/defaults.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
targetGenerator: 'markdown' as const,
|
|
1
|
+
const commonDefaults = {
|
|
3
2
|
targetDir: './docs/',
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export const markdownDefaults = {
|
|
6
|
+
...commonDefaults,
|
|
4
7
|
scope: ['global'],
|
|
5
8
|
defaultGroupName: 'Miscellaneous',
|
|
6
9
|
includeMetadata: false,
|
|
7
|
-
|
|
10
|
+
sortAlphabetically: false,
|
|
8
11
|
linkingStrategy: 'relative' as const,
|
|
12
|
+
referenceGuideTitle: 'Apex Reference Guide',
|
|
13
|
+
excludeTags: [],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const openApiDefaults = {
|
|
17
|
+
...commonDefaults,
|
|
18
|
+
fileName: 'openapi',
|
|
19
|
+
title: 'Apex REST API',
|
|
20
|
+
apiVersion: '1.0.0',
|
|
9
21
|
};
|