@cparra/apexdocs 3.0.0-alpha.9 → 3.0.0-rc.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.
Files changed (82) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +442 -325
  3. package/dist/cli/generate.js +295 -205
  4. package/dist/index.d.ts +15 -17
  5. package/examples/markdown/docs/miscellaneous/Url.md +10 -8
  6. package/examples/markdown/force-app/classes/Url.cls +3 -1
  7. package/examples/markdown-jsconfig/.forceignore +12 -0
  8. package/examples/markdown-jsconfig/apexdocs.config.mjs +21 -0
  9. package/examples/markdown-jsconfig/config/project-scratch-def.json +5 -0
  10. package/examples/markdown-jsconfig/docs/index.md +12 -0
  11. package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +315 -0
  12. package/examples/markdown-jsconfig/force-app/classes/Url.cls +196 -0
  13. package/examples/markdown-jsconfig/package-lock.json +665 -0
  14. package/examples/markdown-jsconfig/package.json +15 -0
  15. package/examples/markdown-jsconfig/sfdx-project.json +12 -0
  16. package/examples/open-api/config/project-scratch-def.json +13 -0
  17. package/examples/open-api/docs/openapi.json +582 -0
  18. package/examples/{force-app → open-api/force-app}/main/default/classes/SampleClass.cls +1 -0
  19. package/examples/open-api/package-lock.json +724 -0
  20. package/examples/open-api/package.json +20 -0
  21. package/examples/open-api/sfdx-project.json +12 -0
  22. package/examples/vitepress/apexdocs.config.ts +7 -2
  23. package/examples/vitepress/docs/index.md +11 -11
  24. package/examples/vitepress/docs/miscellaneous/BaseClass.md +1 -1
  25. package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +2 -2
  26. package/examples/vitepress/docs/miscellaneous/SampleException.md +1 -1
  27. package/examples/vitepress/docs/miscellaneous/SampleInterface.md +6 -6
  28. package/examples/vitepress/docs/miscellaneous/Url.md +3 -3
  29. package/examples/vitepress/docs/sample-enums/SampleEnum.md +3 -3
  30. package/examples/vitepress/docs/samplegroup/SampleClass.md +5 -5
  31. package/examples/vitepress/force-app/main/default/classes/SampleClass.cls +1 -1
  32. package/package.json +2 -2
  33. package/src/application/Apexdocs.ts +39 -7
  34. package/src/application/__tests__/apex-file-reader.spec.ts +0 -17
  35. package/src/application/file-writer.ts +37 -15
  36. package/src/application/generators/markdown.ts +10 -39
  37. package/src/application/generators/openapi.ts +22 -6
  38. package/src/cli/args.ts +4 -1
  39. package/src/cli/commands/markdown.ts +1 -3
  40. package/src/cli/commands/openapi.ts +36 -0
  41. package/src/core/markdown/__test__/generating-class-docs.spec.ts +1 -129
  42. package/src/core/markdown/__test__/generating-docs.spec.ts +111 -0
  43. package/src/core/markdown/__test__/generating-enum-docs.spec.ts +0 -64
  44. package/src/core/markdown/__test__/generating-interface-docs.spec.ts +0 -64
  45. package/src/core/markdown/adapters/documentables.ts +0 -1
  46. package/src/core/markdown/generate-docs.ts +2 -5
  47. package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +306 -0
  48. package/src/core/markdown/reflection/reflect-source.ts +51 -50
  49. package/src/core/openApiSettings.ts +41 -0
  50. package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +2 -2
  51. package/src/core/openapi/open-api-docs-processor.ts +8 -4
  52. package/src/core/openapi/open-api.ts +5 -1
  53. package/src/core/openapi/openapi-type-file.ts +1 -1
  54. package/src/core/openapi/parser.ts +1 -15
  55. package/src/core/openapi/transpiler.ts +0 -5
  56. package/src/core/parse-apex-metadata.ts +21 -5
  57. package/src/core/shared/types.d.ts +18 -17
  58. package/src/index.ts +23 -10
  59. package/src/test-helpers/SettingsBuilder.ts +2 -6
  60. package/examples/force-app/main/default/classes/AnotherInterface.cls +0 -16
  61. package/examples/force-app/main/default/classes/EscapedAnnotations.cls +0 -5
  62. package/examples/force-app/main/default/classes/GrandparentClass.cls +0 -5
  63. package/examples/force-app/main/default/classes/GroupedClass.cls +0 -8
  64. package/examples/force-app/main/default/classes/InterfaceWithInheritance.cls +0 -1
  65. package/examples/force-app/main/default/classes/MemberGrouping.cls +0 -17
  66. package/examples/force-app/main/default/classes/ParentClass.cls +0 -16
  67. package/examples/force-app/main/default/classes/SampleClass.cls-meta.xml +0 -5
  68. package/examples/force-app/main/default/classes/SampleClassWithoutModifier.cls +0 -9
  69. package/examples/force-app/main/default/classes/SampleInterface.cls +0 -16
  70. package/src/core/settings.ts +0 -56
  71. /package/examples/{force-app → open-api/force-app}/main/default/classes/ChildClass.cls +0 -0
  72. /package/examples/{force-app → open-api/force-app}/main/default/restapi/SampleRestResource.cls +0 -0
  73. /package/examples/{force-app → open-api/force-app}/main/default/restapi/SampleRestResourceToSkip.cls +0 -0
  74. /package/examples/{force-app → open-api/force-app}/main/default/restapi/SampleRestResourceWithInnerClass.cls +0 -0
  75. /package/examples/{force-app → open-api/force-app}/main/default/restapi/SampleRestResourceWithoutApexDocs.cls +0 -0
  76. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference1.cls +0 -0
  77. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference2.cls +0 -0
  78. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference3.cls +0 -0
  79. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference4.cls +0 -0
  80. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference5.cls +0 -0
  81. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference6.cls +0 -0
  82. /package/examples/{force-app → open-api/force-app}/main/default/restapi/references/Reference7.cls +0 -0
@@ -1,139 +1,11 @@
1
1
  import { assertEither, extendExpect } from './expect-extensions';
2
2
  import { apexBundleFromRawString, generateDocs } from './test-helpers';
3
3
 
4
- describe('Generates interface documentation', () => {
4
+ describe('When generating documentation for a class', () => {
5
5
  beforeAll(() => {
6
6
  extendExpect();
7
7
  });
8
8
 
9
- describe('documentation output', () => {
10
- it('returns the name of the class', async () => {
11
- const input = 'public class MyClass {}';
12
-
13
- const result = await generateDocs([apexBundleFromRawString(input)])();
14
- expect(result).documentationBundleHasLength(1);
15
- assertEither(result, (data) => expect(data.docs[0].outputDocPath).toContain('MyClass'));
16
- });
17
-
18
- it('returns the type as class', async () => {
19
- const input = 'public class MyClass {}';
20
-
21
- const result = await generateDocs([apexBundleFromRawString(input)])();
22
- expect(result).documentationBundleHasLength(1);
23
- assertEither(result, (data) => expect(data.docs[0].source.type).toBe('class'));
24
- });
25
-
26
- it('does not return classes out of scope', async () => {
27
- const input1 = `
28
- global class MyClass {}
29
- `;
30
-
31
- const input2 = `
32
- public class AnotherClass {}
33
- `;
34
-
35
- const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
36
- scope: ['global'],
37
- })();
38
- expect(result).documentationBundleHasLength(1);
39
- });
40
-
41
- it('does not return classes that have an @ignore in the docs', async () => {
42
- const input = `
43
- /**
44
- * @ignore
45
- */
46
- public class MyClass {}`;
47
-
48
- const result = await generateDocs([apexBundleFromRawString(input)])();
49
- expect(result).documentationBundleHasLength(0);
50
- });
51
-
52
- it('does not return class methods that have @ignore in the docs', async () => {
53
- const input = `
54
- public class MyClass {
55
- /**
56
- * @ignore
57
- */
58
- public void myMethod() {}
59
- }`;
60
-
61
- const result = await generateDocs([apexBundleFromRawString(input)])();
62
- expect(result).documentationBundleHasLength(1);
63
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myMethod'));
64
- });
65
-
66
- it('does not return class properties that have @ignore in the docs', async () => {
67
- const input = `
68
- public class MyClass {
69
- /**
70
- * @ignore
71
- */
72
- public String myProperty { get; set; }
73
- }`;
74
-
75
- const result = await generateDocs([apexBundleFromRawString(input)])();
76
- expect(result).documentationBundleHasLength(1);
77
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myProperty'));
78
- });
79
-
80
- it('does not return class fields that have @ignore in the docs', async () => {
81
- const input = `
82
- public class MyClass {
83
- /**
84
- * @ignore
85
- */
86
- public String myField;
87
- }`;
88
-
89
- const result = await generateDocs([apexBundleFromRawString(input)])();
90
- expect(result).documentationBundleHasLength(1);
91
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myField'));
92
- });
93
-
94
- it('does not return class inner classes that have @ignore in the docs', async () => {
95
- const input = `
96
- public class MyClass {
97
- /**
98
- * @ignore
99
- */
100
- public class InnerClass {}
101
- }`;
102
-
103
- const result = await generateDocs([apexBundleFromRawString(input)])();
104
- expect(result).documentationBundleHasLength(1);
105
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerClass'));
106
- });
107
-
108
- it('does not return class inner interfaces that have @ignore in the docs', async () => {
109
- const input = `
110
- public class MyClass {
111
- /**
112
- * @ignore
113
- */
114
- public interface InnerInterface {}
115
- }`;
116
-
117
- const result = await generateDocs([apexBundleFromRawString(input)])();
118
- expect(result).documentationBundleHasLength(1);
119
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerInterface'));
120
- });
121
-
122
- it('does not return class inner enums that have @ignore in the docs', async () => {
123
- const input = `
124
- public class MyClass {
125
- /**
126
- * @ignore
127
- */
128
- public enum InnerEnum {}
129
- }`;
130
-
131
- const result = await generateDocs([apexBundleFromRawString(input)])();
132
- expect(result).documentationBundleHasLength(1);
133
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('InnerEnum'));
134
- });
135
- });
136
-
137
9
  describe('documentation content', () => {
138
10
  describe('type level information', () => {
139
11
  it('generates a heading with the class name', async () => {
@@ -0,0 +1,111 @@
1
+ import { DocPageData, PostHookDocumentationBundle } from '../../shared/types';
2
+ import { assertEither, extendExpect } from './expect-extensions';
3
+ import { apexBundleFromRawString, generateDocs } from './test-helpers';
4
+
5
+ function aSingleDoc(result: PostHookDocumentationBundle): DocPageData {
6
+ expect(result.docs).toHaveLength(1);
7
+ return result.docs[0];
8
+ }
9
+
10
+ describe('When generating documentation', () => {
11
+ beforeAll(() => {
12
+ extendExpect();
13
+ });
14
+
15
+ describe('the resulting files', () => {
16
+ it('are named after the type', async () => {
17
+ const properties: [string, string][] = [
18
+ ['public class MyClass {}', 'MyClass.md'],
19
+ ['public interface MyInterface {}', 'MyInterface.md'],
20
+ ['public enum MyEnum {}', 'MyEnum.md'],
21
+ ];
22
+
23
+ for (const [input, expected] of properties) {
24
+ const result = await generateDocs([apexBundleFromRawString(input)])();
25
+ assertEither(result, (data) => expect(aSingleDoc(data).outputDocPath).toContain(expected));
26
+ }
27
+ });
28
+
29
+ it('are placed in the miscellaneous folder if no group is provided', async () => {
30
+ const properties: [string, string][] = [
31
+ ['public class MyClass {}', 'miscellaneous'],
32
+ ['public interface MyInterface {}', 'miscellaneous'],
33
+ ['public enum MyEnum {}', 'miscellaneous'],
34
+ ];
35
+
36
+ for (const [input, expected] of properties) {
37
+ const result = await generateDocs([apexBundleFromRawString(input)])();
38
+ assertEither(result, (data) => expect(aSingleDoc(data).outputDocPath).toContain(expected));
39
+ }
40
+ });
41
+
42
+ it('are placed in the slugified group folder if a group is provided', async () => {
43
+ const properties: [string, string][] = [
44
+ [
45
+ `/**
46
+ * @group MyGroup
47
+ */
48
+ public class MyClass {}`,
49
+ 'mygroup',
50
+ ],
51
+ [
52
+ `/**
53
+ * @group MyGroup
54
+ */
55
+ public interface MyInterface {}`,
56
+ 'mygroup',
57
+ ],
58
+ [
59
+ `/**
60
+ * @group MyGroup
61
+ */
62
+ public enum MyEnum {}`,
63
+ 'mygroup',
64
+ ],
65
+ ];
66
+
67
+ for (const [input, expected] of properties) {
68
+ const result = await generateDocs([apexBundleFromRawString(input)])();
69
+ assertEither(result, (data) => expect(aSingleDoc(data).outputDocPath).toContain(expected));
70
+ }
71
+ });
72
+ });
73
+
74
+ describe('the generated bundles', () => {
75
+ it('return the type', async () => {
76
+ const properties: [string, string][] = [
77
+ ['public class MyClass {}', 'class'],
78
+ ['public interface MyInterface {}', 'interface'],
79
+ ['public enum MyEnum {}', 'enum'],
80
+ ];
81
+
82
+ for (const [input, expected] of properties) {
83
+ const result = await generateDocs([apexBundleFromRawString(input)])();
84
+ assertEither(result, (data) => expect(aSingleDoc(data).source.type).toBe(expected));
85
+ }
86
+ });
87
+ });
88
+
89
+ describe('the generated bundle', () => {
90
+ it('does not return files out of scope', async () => {
91
+ const input1 = 'global class MyClass {}';
92
+ const input2 = 'public class AnotherClass {}';
93
+
94
+ const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
95
+ scope: ['global'],
96
+ })();
97
+ expect(result).documentationBundleHasLength(1);
98
+ });
99
+
100
+ it('does not return files that have an @ignore in the docs', async () => {
101
+ const input = `
102
+ /**
103
+ * @ignore
104
+ */
105
+ public class MyClass {}`;
106
+
107
+ const result = await generateDocs([apexBundleFromRawString(input)])();
108
+ expect(result).documentationBundleHasLength(0);
109
+ });
110
+ });
111
+ });
@@ -6,70 +6,6 @@ describe('Generates enum documentation', () => {
6
6
  extendExpect();
7
7
  });
8
8
 
9
- describe('documentation output', () => {
10
- it('returns the name of the enum', async () => {
11
- const input = `
12
- public enum MyEnum {
13
- VALUE1,
14
- VALUE2
15
- }
16
- `;
17
-
18
- const result = await generateDocs([apexBundleFromRawString(input)])();
19
- expect(result).documentationBundleHasLength(1);
20
- assertEither(result, (data) => expect(data.docs[0].outputDocPath).toContain('MyEnum'));
21
- });
22
-
23
- it('returns the type as enum', async () => {
24
- const input = `
25
- public enum MyEnum {
26
- VALUE1,
27
- VALUE2
28
- }
29
- `;
30
-
31
- const result = await generateDocs([apexBundleFromRawString(input)])();
32
- expect(result).documentationBundleHasLength(1);
33
- assertEither(result, (data) => expect(data.docs[0].source.type).toBe('enum'));
34
- });
35
-
36
- it('does not return enums out of scope', async () => {
37
- const input1 = `
38
- global enum MyEnum {
39
- VALUE1,
40
- VALUE2
41
- }
42
- `;
43
-
44
- const input2 = `
45
- public enum MyEnum {
46
- VALUE1,
47
- VALUE2
48
- }
49
- `;
50
-
51
- const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
52
- scope: ['global'],
53
- })();
54
- expect(result).documentationBundleHasLength(1);
55
- });
56
-
57
- it('does not return enums that have an @ignore in the docs', async () => {
58
- const input = `
59
- /**
60
- * @ignore
61
- */
62
- public enum MyEnum {
63
- VALUE1,
64
- VALUE2
65
- }
66
- `;
67
-
68
- const result = await generateDocs([apexBundleFromRawString(input)])();
69
- expect(result).documentationBundleHasLength(0);
70
- });
71
- });
72
-
73
9
  describe('documentation content', () => {
74
10
  it('generates a heading with the enum name', async () => {
75
11
  const input = `
@@ -6,70 +6,6 @@ describe('Generates interface documentation', () => {
6
6
  extendExpect();
7
7
  });
8
8
 
9
- describe('documentation output', () => {
10
- it('returns the name of the interface', async () => {
11
- const input = `
12
- public interface MyInterface {
13
- }
14
- `;
15
-
16
- const result = await generateDocs([apexBundleFromRawString(input)])();
17
- expect(result).documentationBundleHasLength(1);
18
- assertEither(result, (data) => expect(data.docs[0].source.name).toBe('MyInterface'));
19
- });
20
-
21
- it('returns the type as interface', async () => {
22
- const input = `
23
- public interface MyInterface {
24
- }
25
- `;
26
-
27
- const result = await generateDocs([apexBundleFromRawString(input)])();
28
- expect(result).documentationBundleHasLength(1);
29
- assertEither(result, (data) => expect(data.docs[0].source.type).toBe('interface'));
30
- });
31
-
32
- it('does not return interfaces out of scope', async () => {
33
- const input1 = `
34
- global interface MyInterface {}
35
- `;
36
-
37
- const input2 = `
38
- public interface AnotherInterface {}
39
- `;
40
-
41
- const result = await generateDocs([apexBundleFromRawString(input1), apexBundleFromRawString(input2)], {
42
- scope: ['global'],
43
- })();
44
- expect(result).documentationBundleHasLength(1);
45
- });
46
-
47
- it('does not return interfaces that have an @ignore in the docs', async () => {
48
- const input = `
49
- /**
50
- * @ignore
51
- */
52
- public interface MyInterface {}`;
53
-
54
- const result = await generateDocs([apexBundleFromRawString(input)])();
55
- expect(result).documentationBundleHasLength(0);
56
- });
57
-
58
- it('does not return interface methods that have @ignore in the docs', async () => {
59
- const input = `
60
- public interface MyInterface {
61
- /**
62
- * @ignore
63
- */
64
- void myMethod();
65
- }`;
66
-
67
- const result = await generateDocs([apexBundleFromRawString(input)])();
68
- expect(result).documentationBundleHasLength(1);
69
- assertEither(result, (data) => expect(data.docs[0].content).not.toContain('myMethod'));
70
- });
71
- });
72
-
73
9
  describe('documentation content', () => {
74
10
  describe('type level information', () => {
75
11
  it('generates a heading with the interface name', async () => {
@@ -98,7 +98,6 @@ export function adaptDocumentable(
98
98
  .map((currentAnnotation) => currentAnnotation.body) ?? []
99
99
  );
100
100
  }
101
-
102
101
  return {
103
102
  ...adaptDescribable(documentable.docComment?.descriptionLines, linkGenerator),
104
103
  annotations: documentable.annotations.map((annotation) => annotation.type.toUpperCase()),
@@ -1,5 +1,4 @@
1
1
  import { pipe } from 'fp-ts/function';
2
- //import * as E from 'fp-ts/Either';
3
2
  import * as TE from 'fp-ts/TaskEither';
4
3
  import yaml from 'js-yaml';
5
4
 
@@ -20,8 +19,7 @@ import {
20
19
  ParsedFile,
21
20
  } from '../shared/types';
22
21
  import { parsedFilesToRenderableBundle } from './adapters/renderable-bundle';
23
- import { myPipeSeq /*reflectSourceCode*/ } from './reflection/reflect-source';
24
- //import { checkForReflectionErrors } from './reflection/error-handling';
22
+ import { reflectBundles } from './reflection/reflect-source';
25
23
  import { addInheritanceChainToTypes } from './reflection/inheritance-chain-expanion';
26
24
  import { addInheritedMembersToTypes } from './reflection/inherited-member-expansion';
27
25
  import { convertToDocumentationBundle } from './adapters/renderable-to-page-data';
@@ -63,8 +61,7 @@ export function generateDocs(apexBundles: UnparsedSourceFile[], config: Markdown
63
61
 
64
62
  return pipe(
65
63
  apexBundles,
66
- myPipeSeq,
67
- //checkForReflectionErrors,
64
+ reflectBundles,
68
65
  TE.map(filterOutOfScope),
69
66
  TE.map(addInheritedMembersToTypes),
70
67
  TE.map(addInheritanceChainToTypes),