@cparra/apexdocs 3.0.0-rc.0 → 3.1.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 (226) hide show
  1. package/README.md +61 -576
  2. package/dist/cli/generate.js +73 -3094
  3. package/dist/defaults-BcE8DTat.js +13 -0
  4. package/dist/defaults-D07y_bq4.js +40 -0
  5. package/dist/defaults-gPzwP66p.js +14 -0
  6. package/dist/index.d.ts +35 -3
  7. package/dist/index.js +90 -2
  8. package/dist/logger-BEbUIfqN.js +3282 -0
  9. package/dist/logger-BGuf1PnL.js +3281 -0
  10. package/dist/logger-CWBRF2za.js +3284 -0
  11. package/dist/logger-CdBmDEN1.js +3283 -0
  12. package/dist/logger-Ce4QqPFR.js +3278 -0
  13. package/dist/logger-CyEVYaAC.js +3284 -0
  14. package/dist/logger-D7a83ycP.js +3277 -0
  15. package/dist/logger-DGaHeBKk.js +3279 -0
  16. package/dist/logger-Dqhl_lO_.js +3278 -0
  17. package/dist/logger-aySSWi0G.js +3280 -0
  18. package/dist/logger-qLCcAtiy.js +3284 -0
  19. package/package.json +5 -2
  20. package/.github/workflows/ci.yaml +0 -22
  21. package/.github/workflows/close_stale.yml +0 -22
  22. package/.prettierrc.js +0 -7
  23. package/__mocks__/chalk.js +0 -12
  24. package/__mocks__/log-update.js +0 -6
  25. package/eslint.config.mjs +0 -10
  26. package/examples/markdown/.forceignore +0 -12
  27. package/examples/markdown/config/project-scratch-def.json +0 -5
  28. package/examples/markdown/docs/index.md +0 -109
  29. package/examples/markdown/docs/miscellaneous/BaseClass.md +0 -16
  30. package/examples/markdown/docs/miscellaneous/MultiInheritanceClass.md +0 -72
  31. package/examples/markdown/docs/miscellaneous/ParentInterface.md +0 -15
  32. package/examples/markdown/docs/miscellaneous/ReferencedEnum.md +0 -8
  33. package/examples/markdown/docs/miscellaneous/SampleException.md +0 -24
  34. package/examples/markdown/docs/miscellaneous/SampleInterface.md +0 -116
  35. package/examples/markdown/docs/miscellaneous/Url.md +0 -311
  36. package/examples/markdown/docs/sample-enums/SampleEnum.md +0 -36
  37. package/examples/markdown/docs/samplegroup/SampleClass.md +0 -170
  38. package/examples/markdown/force-app/classes/BaseClass.cls +0 -3
  39. package/examples/markdown/force-app/classes/MultiInheritanceClass.cls +0 -1
  40. package/examples/markdown/force-app/classes/ParentInterface.cls +0 -3
  41. package/examples/markdown/force-app/classes/ReferencedEnum.cls +0 -3
  42. package/examples/markdown/force-app/classes/SampleClass.cls +0 -72
  43. package/examples/markdown/force-app/classes/SampleEnum.cls +0 -30
  44. package/examples/markdown/force-app/classes/SampleException.cls +0 -17
  45. package/examples/markdown/force-app/classes/SampleInterface.cls +0 -50
  46. package/examples/markdown/force-app/classes/Url.cls +0 -196
  47. package/examples/markdown/package-lock.json +0 -665
  48. package/examples/markdown/package.json +0 -20
  49. package/examples/markdown/sfdx-project.json +0 -12
  50. package/examples/markdown-jsconfig/.forceignore +0 -12
  51. package/examples/markdown-jsconfig/apexdocs.config.mjs +0 -21
  52. package/examples/markdown-jsconfig/config/project-scratch-def.json +0 -5
  53. package/examples/markdown-jsconfig/docs/index.md +0 -12
  54. package/examples/markdown-jsconfig/docs/miscellaneous/Url.md +0 -315
  55. package/examples/markdown-jsconfig/force-app/classes/Url.cls +0 -196
  56. package/examples/markdown-jsconfig/package-lock.json +0 -665
  57. package/examples/markdown-jsconfig/package.json +0 -15
  58. package/examples/markdown-jsconfig/sfdx-project.json +0 -12
  59. package/examples/open-api/config/project-scratch-def.json +0 -13
  60. package/examples/open-api/docs/openapi.json +0 -582
  61. package/examples/open-api/force-app/main/default/classes/ChildClass.cls +0 -42
  62. package/examples/open-api/force-app/main/default/classes/SampleClass.cls +0 -167
  63. package/examples/open-api/force-app/main/default/restapi/SampleRestResource.cls +0 -195
  64. package/examples/open-api/force-app/main/default/restapi/SampleRestResourceToSkip.cls +0 -35
  65. package/examples/open-api/force-app/main/default/restapi/SampleRestResourceWithInnerClass.cls +0 -24
  66. package/examples/open-api/force-app/main/default/restapi/SampleRestResourceWithoutApexDocs.cls +0 -15
  67. package/examples/open-api/force-app/main/default/restapi/references/Reference1.cls +0 -9
  68. package/examples/open-api/force-app/main/default/restapi/references/Reference2.cls +0 -9
  69. package/examples/open-api/force-app/main/default/restapi/references/Reference3.cls +0 -3
  70. package/examples/open-api/force-app/main/default/restapi/references/Reference4.cls +0 -3
  71. package/examples/open-api/force-app/main/default/restapi/references/Reference5.cls +0 -3
  72. package/examples/open-api/force-app/main/default/restapi/references/Reference6.cls +0 -6
  73. package/examples/open-api/force-app/main/default/restapi/references/Reference7.cls +0 -3
  74. package/examples/open-api/package-lock.json +0 -724
  75. package/examples/open-api/package.json +0 -20
  76. package/examples/open-api/sfdx-project.json +0 -12
  77. package/examples/vitepress/.forceignore +0 -12
  78. package/examples/vitepress/apexdocs.config.ts +0 -111
  79. package/examples/vitepress/config/project-scratch-def.json +0 -13
  80. package/examples/vitepress/docs/.vitepress/cache/deps/@theme_index.js +0 -259
  81. package/examples/vitepress/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
  82. package/examples/vitepress/docs/.vitepress/cache/deps/_metadata.json +0 -40
  83. package/examples/vitepress/docs/.vitepress/cache/deps/chunk-574YRH25.js +0 -11474
  84. package/examples/vitepress/docs/.vitepress/cache/deps/chunk-574YRH25.js.map +0 -7
  85. package/examples/vitepress/docs/.vitepress/cache/deps/chunk-E5DZZB2I.js +0 -9172
  86. package/examples/vitepress/docs/.vitepress/cache/deps/chunk-E5DZZB2I.js.map +0 -7
  87. package/examples/vitepress/docs/.vitepress/cache/deps/package.json +0 -3
  88. package/examples/vitepress/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4339
  89. package/examples/vitepress/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  90. package/examples/vitepress/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -567
  91. package/examples/vitepress/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  92. package/examples/vitepress/docs/.vitepress/cache/deps/vue.js +0 -323
  93. package/examples/vitepress/docs/.vitepress/cache/deps/vue.js.map +0 -7
  94. package/examples/vitepress/docs/.vitepress/config.mts +0 -21
  95. package/examples/vitepress/docs/.vitepress/sidebar.json +0 -119
  96. package/examples/vitepress/docs/api-examples.md +0 -49
  97. package/examples/vitepress/docs/index-frontmatter.md +0 -16
  98. package/examples/vitepress/docs/index.md +0 -56
  99. package/examples/vitepress/docs/markdown-examples.md +0 -85
  100. package/examples/vitepress/docs/miscellaneous/BaseClass.md +0 -20
  101. package/examples/vitepress/docs/miscellaneous/MultiInheritanceClass.md +0 -76
  102. package/examples/vitepress/docs/miscellaneous/ParentInterface.md +0 -19
  103. package/examples/vitepress/docs/miscellaneous/ReferencedEnum.md +0 -15
  104. package/examples/vitepress/docs/miscellaneous/SampleException.md +0 -28
  105. package/examples/vitepress/docs/miscellaneous/SampleInterface.md +0 -116
  106. package/examples/vitepress/docs/miscellaneous/Url.md +0 -317
  107. package/examples/vitepress/docs/sample-enums/SampleEnum.md +0 -40
  108. package/examples/vitepress/docs/samplegroup/SampleClass.md +0 -174
  109. package/examples/vitepress/force-app/main/default/classes/BaseClass.cls +0 -3
  110. package/examples/vitepress/force-app/main/default/classes/MultiInheritanceClass.cls +0 -1
  111. package/examples/vitepress/force-app/main/default/classes/ParentInterface.cls +0 -3
  112. package/examples/vitepress/force-app/main/default/classes/ReferencedEnum.cls +0 -5
  113. package/examples/vitepress/force-app/main/default/classes/SampleClass.cls +0 -72
  114. package/examples/vitepress/force-app/main/default/classes/SampleEnum.cls +0 -30
  115. package/examples/vitepress/force-app/main/default/classes/SampleException.cls +0 -17
  116. package/examples/vitepress/force-app/main/default/classes/SampleInterface.cls +0 -46
  117. package/examples/vitepress/force-app/main/default/classes/Url.cls +0 -198
  118. package/examples/vitepress/package-lock.json +0 -2574
  119. package/examples/vitepress/package.json +0 -18
  120. package/examples/vitepress/sfdx-project.json +0 -12
  121. package/jest.config.js +0 -10
  122. package/jest.d.ts +0 -7
  123. package/src/application/Apexdocs.ts +0 -72
  124. package/src/application/__tests__/apex-file-reader.spec.ts +0 -87
  125. package/src/application/apex-file-reader.ts +0 -55
  126. package/src/application/file-system.ts +0 -69
  127. package/src/application/file-writer.ts +0 -43
  128. package/src/application/generators/markdown.ts +0 -45
  129. package/src/application/generators/openapi.ts +0 -71
  130. package/src/cli/args.ts +0 -46
  131. package/src/cli/commands/markdown.ts +0 -51
  132. package/src/cli/commands/openapi.ts +0 -36
  133. package/src/cli/generate.ts +0 -16
  134. package/src/core/__test__/manifest.spec.ts +0 -16
  135. package/src/core/manifest.ts +0 -90
  136. package/src/core/markdown/__test__/expect-extensions.ts +0 -32
  137. package/src/core/markdown/__test__/generating-class-docs.spec.ts +0 -605
  138. package/src/core/markdown/__test__/generating-docs.spec.ts +0 -111
  139. package/src/core/markdown/__test__/generating-enum-docs.spec.ts +0 -321
  140. package/src/core/markdown/__test__/generating-interface-docs.spec.ts +0 -397
  141. package/src/core/markdown/__test__/generating-reference-guide.spec.ts +0 -180
  142. package/src/core/markdown/__test__/inheritance-chain.test.ts +0 -54
  143. package/src/core/markdown/__test__/test-helpers.ts +0 -23
  144. package/src/core/markdown/adapters/__tests__/documentables.spec.ts +0 -109
  145. package/src/core/markdown/adapters/__tests__/interface-adapter.spec.ts +0 -148
  146. package/src/core/markdown/adapters/__tests__/link-generator.spec.ts +0 -130
  147. package/src/core/markdown/adapters/__tests__/references.spec.ts +0 -136
  148. package/src/core/markdown/adapters/apex-types.ts +0 -238
  149. package/src/core/markdown/adapters/documentables.ts +0 -115
  150. package/src/core/markdown/adapters/fields-and-properties.ts +0 -45
  151. package/src/core/markdown/adapters/generate-link.ts +0 -82
  152. package/src/core/markdown/adapters/inline.ts +0 -143
  153. package/src/core/markdown/adapters/methods-and-constructors.ts +0 -133
  154. package/src/core/markdown/adapters/reference-guide.ts +0 -37
  155. package/src/core/markdown/adapters/renderable-bundle.ts +0 -61
  156. package/src/core/markdown/adapters/renderable-to-page-data.ts +0 -89
  157. package/src/core/markdown/adapters/type-utils.ts +0 -13
  158. package/src/core/markdown/adapters/types.d.ts +0 -180
  159. package/src/core/markdown/generate-docs.ts +0 -212
  160. package/src/core/markdown/reflection/__test__/filter-scope.spec.ts +0 -306
  161. package/src/core/markdown/reflection/filter-scope.ts +0 -13
  162. package/src/core/markdown/reflection/inheritance-chain-expanion.ts +0 -22
  163. package/src/core/markdown/reflection/inheritance-chain.ts +0 -23
  164. package/src/core/markdown/reflection/inherited-member-expansion.ts +0 -105
  165. package/src/core/markdown/reflection/reflect-source.ts +0 -123
  166. package/src/core/markdown/reflection/sort-members.ts +0 -59
  167. package/src/core/markdown/templates/class-template.ts +0 -75
  168. package/src/core/markdown/templates/constructors-partial-template.ts +0 -32
  169. package/src/core/markdown/templates/documentable-partial-template.ts +0 -26
  170. package/src/core/markdown/templates/enum-template.ts +0 -12
  171. package/src/core/markdown/templates/fieldsPartialTemplate.ts +0 -23
  172. package/src/core/markdown/templates/grouped-members-partial-template.ts +0 -6
  173. package/src/core/markdown/templates/hookable.ts +0 -7
  174. package/src/core/markdown/templates/interface-template.ts +0 -16
  175. package/src/core/markdown/templates/methods-partial-template.ts +0 -43
  176. package/src/core/markdown/templates/reference-guide.ts +0 -14
  177. package/src/core/markdown/templates/template.ts +0 -114
  178. package/src/core/markdown/templates/type-doc-partial.ts +0 -27
  179. package/src/core/markdown/utils.ts +0 -3
  180. package/src/core/openApiSettings.ts +0 -41
  181. package/src/core/openapi/__tests__/manifest-factory.spec.ts +0 -16
  182. package/src/core/openapi/__tests__/open-api-docs-processor.spec.ts +0 -56
  183. package/src/core/openapi/__tests__/open-api.spec.ts +0 -22
  184. package/src/core/openapi/apex-doc-types.ts +0 -26
  185. package/src/core/openapi/apex-type-wrappers/ClassMirrorWrapper.ts +0 -12
  186. package/src/core/openapi/apex-type-wrappers/MethodMirrorWrapper.ts +0 -11
  187. package/src/core/openapi/apex-type-wrappers/__tests__/ClassMirrorWrapper.spec.ts +0 -15
  188. package/src/core/openapi/file-container.ts +0 -13
  189. package/src/core/openapi/manifest-factory.ts +0 -16
  190. package/src/core/openapi/open-api-docs-processor.ts +0 -93
  191. package/src/core/openapi/open-api-types.ts +0 -119
  192. package/src/core/openapi/open-api.ts +0 -45
  193. package/src/core/openapi/openapi-type-file.ts +0 -12
  194. package/src/core/openapi/parser.ts +0 -160
  195. package/src/core/openapi/parsers/Builder.ts +0 -40
  196. package/src/core/openapi/parsers/MethodParser.ts +0 -249
  197. package/src/core/openapi/parsers/ParameterObjectBuilder.ts +0 -13
  198. package/src/core/openapi/parsers/ReferenceBuilder.ts +0 -299
  199. package/src/core/openapi/parsers/RequestBodyBuilder.ts +0 -19
  200. package/src/core/openapi/parsers/ResponsesBuilder.ts +0 -21
  201. package/src/core/openapi/parsers/__tests__/MethodParser.spec.ts +0 -44
  202. package/src/core/openapi/parsers/__tests__/ParameterObjectBuilder.spec.ts +0 -68
  203. package/src/core/openapi/parsers/__tests__/ReferenceBuilder.spec.ts +0 -751
  204. package/src/core/openapi/parsers/__tests__/RequestBodyBuilder.spec.ts +0 -64
  205. package/src/core/openapi/parsers/__tests__/ResponsesBuilder.spec.ts +0 -55
  206. package/src/core/openapi/transpiler.ts +0 -17
  207. package/src/core/openapi/types-repository.ts +0 -54
  208. package/src/core/parse-apex-metadata.ts +0 -30
  209. package/src/core/shared/types.d.ts +0 -148
  210. package/src/core/shared/utils.ts +0 -5
  211. package/src/defaults.ts +0 -9
  212. package/src/index.ts +0 -49
  213. package/src/test-helpers/AnnotationBuilder.ts +0 -29
  214. package/src/test-helpers/ClassMirrorBuilder.ts +0 -69
  215. package/src/test-helpers/DocCommentAnnotationBuilder.ts +0 -24
  216. package/src/test-helpers/DocCommentBuilder.ts +0 -36
  217. package/src/test-helpers/FieldMirrorBuilder.ts +0 -59
  218. package/src/test-helpers/InterfaceMirrorBuilder.ts +0 -39
  219. package/src/test-helpers/MethodMirrorBuilder.ts +0 -77
  220. package/src/test-helpers/SettingsBuilder.ts +0 -17
  221. package/src/util/error-logger.ts +0 -92
  222. package/src/util/fp.ts +0 -3
  223. package/src/util/logger.ts +0 -44
  224. package/src/util/string-utils.ts +0 -7
  225. package/tsconfig.json +0 -25
  226. package/tslint.json +0 -6
@@ -1,249 +0,0 @@
1
- import { ClassMirror, MethodMirror } from '@cparra/apex-reflection';
2
- import { OpenApi } from '../../../core/openapi/open-api';
3
- import * as yaml from 'js-yaml';
4
- import { ClassMirrorWrapper } from '../../../core/openapi/apex-type-wrappers/ClassMirrorWrapper';
5
- import { Reference, ReferenceBuilder } from './ReferenceBuilder';
6
- import { ParameterObjectBuilder } from './ParameterObjectBuilder';
7
- import { ResponsesBuilder } from './ResponsesBuilder';
8
- import {
9
- ApexDocHttpRequestBody,
10
- ApexDocHttpResponse,
11
- ApexDocParameterObject,
12
- } from '../../../core/openapi/apex-doc-types';
13
- import { RequestBodyBuilder } from './RequestBodyBuilder';
14
- import { ApexDocSchemaAware } from './Builder';
15
- import { PropertiesObject, ReferenceObject } from '../../../core/openapi/open-api-types';
16
- import { MethodMirrorWrapper } from '../../../core/openapi/apex-type-wrappers/MethodMirrorWrapper';
17
-
18
- type FallbackMethodParser = (methodMirror: MethodMirror) => void;
19
- type AddToOpenApi<T extends ApexDocSchemaAware> = (input: T, urlValue: string, httpMethodKey: HttpOperations) => void;
20
-
21
- type HttpOperations = 'get' | 'put' | 'post' | 'delete' | 'patch';
22
-
23
- /**
24
- * Parses ApexDocs with HTTP REST annotations and turns them into an OpenApi specification.
25
- */
26
- export class MethodParser {
27
- constructor(public openApiModel: OpenApi) {}
28
-
29
- public parseMethod(classMirror: ClassMirror, httpUrlEndpoint: string, httpMethodKey: HttpOperations, tag: string) {
30
- const classMirrorWrapper = new ClassMirrorWrapper(classMirror);
31
- // Apex supports HttpGet, HttpPut, HttpPost, HttpDelete, and HttpPatch, so we search for a method
32
- // that has one of those annotations.
33
- const httpMethods = classMirrorWrapper.getMethodsByAnnotation(`http${httpMethodKey}`);
34
- if (!httpMethods.length) {
35
- return;
36
- }
37
-
38
- // We can assume there is at most one method per annotation, as this is an Apex rule.
39
- const httpMethod = httpMethods[0];
40
-
41
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey] = {};
42
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.tags = [tag];
43
- if (httpMethod.docComment?.description) {
44
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.description = httpMethod.docComment.description;
45
- }
46
- const methodMirrorWrapper = new MethodMirrorWrapper(httpMethod);
47
- if (methodMirrorWrapper.hasDocCommentAnnotation('summary')) {
48
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.summary =
49
- methodMirrorWrapper.getDocCommentAnnotation('summary')?.body;
50
- }
51
-
52
- this.parseHttpAnnotation<ApexDocHttpRequestBody>(
53
- httpMethod,
54
- httpUrlEndpoint,
55
- httpMethodKey,
56
- 'http-request-body',
57
- this.addRequestBodyToOpenApi.bind(this),
58
- this.fallbackHttpRequestBodyParser(httpUrlEndpoint, httpMethodKey),
59
- );
60
-
61
- this.parseHttpAnnotation<ApexDocParameterObject>(
62
- httpMethod,
63
- httpUrlEndpoint,
64
- httpMethodKey,
65
- 'http-parameter',
66
- this.addParametersToOpenApi.bind(this),
67
- );
68
-
69
- this.parseHttpAnnotation<ApexDocHttpResponse>(
70
- httpMethod,
71
- httpUrlEndpoint,
72
- httpMethodKey,
73
- 'http-response',
74
- this.addHttpResponsesToOpenApi.bind(this),
75
- this.getFallbackHttpResponseParser(httpUrlEndpoint, httpMethodKey),
76
- );
77
- }
78
-
79
- private parseHttpAnnotation<T extends ApexDocSchemaAware>(
80
- httpMethod: MethodMirror,
81
- urlValue: string,
82
- httpMethodKey: HttpOperations,
83
- annotationName: string,
84
- addToOpenApi: AddToOpenApi<T>,
85
- fallbackParser?: FallbackMethodParser,
86
- ) {
87
- const annotations = httpMethod.docComment?.annotations.filter((annotation) => annotation.name === annotationName);
88
-
89
- if (!annotations?.length) {
90
- if (fallbackParser) {
91
- fallbackParser(httpMethod);
92
- }
93
- return;
94
- }
95
-
96
- for (const annotation of annotations) {
97
- // We expect the ApexDoc data representing this to be in YAML format.
98
- const inYaml = annotation?.bodyLines.reduce((prev, current) => prev + '\n' + current);
99
-
100
- if (!inYaml) {
101
- return;
102
- }
103
-
104
- this.addToOpenApiStrategy<T>(inYaml, urlValue, httpMethodKey, addToOpenApi);
105
- }
106
- }
107
-
108
- private addToOpenApiStrategy<T extends ApexDocSchemaAware>(
109
- inYaml: string,
110
- urlValue: string,
111
- httpMethodKey: HttpOperations,
112
- addToOpenApi: AddToOpenApi<T>,
113
- ): void {
114
- // Convert the YAML into a JSON object.
115
- const inJson = yaml.load(inYaml) as T;
116
- const requestBodyResponse = new RequestBodyBuilder().build(inJson);
117
-
118
- addToOpenApi(inJson, urlValue, httpMethodKey);
119
-
120
- this.addReference(requestBodyResponse);
121
- }
122
-
123
- private addRequestBodyToOpenApi(
124
- input: ApexDocHttpRequestBody,
125
- urlValue: string,
126
- httpMethodKey: HttpOperations,
127
- ): void {
128
- const requestBodyResponse = new RequestBodyBuilder().build(input);
129
- this.openApiModel.paths[urlValue][httpMethodKey]!.requestBody = requestBodyResponse.body;
130
- }
131
-
132
- private addParametersToOpenApi(input: ApexDocParameterObject, urlValue: string, httpMethodKey: HttpOperations): void {
133
- const parameterObjectResponse = new ParameterObjectBuilder().build(input);
134
-
135
- if (this.openApiModel.paths[urlValue][httpMethodKey]!.parameters === undefined) {
136
- // If no parameters have been defined yet, initialize the list.
137
- this.openApiModel.paths[urlValue][httpMethodKey]!.parameters = [];
138
- }
139
- this.openApiModel.paths[urlValue][httpMethodKey]!.parameters!.push(parameterObjectResponse.body);
140
- }
141
-
142
- private addHttpResponsesToOpenApi(input: ApexDocHttpResponse, urlValue: string, httpMethodKey: HttpOperations): void {
143
- const responseObjectResponse = new ResponsesBuilder().build(input);
144
-
145
- if (this.openApiModel.paths[urlValue][httpMethodKey]!.responses === undefined) {
146
- this.openApiModel.paths[urlValue][httpMethodKey]!.responses = {};
147
- }
148
-
149
- this.openApiModel.paths[urlValue][httpMethodKey]!.responses![input.statusCode] = responseObjectResponse.body;
150
- }
151
-
152
- private fallbackHttpRequestBodyParser(
153
- httpUrlEndpoint: string,
154
- httpMethodKey: 'get' | 'put' | 'post' | 'delete' | 'patch',
155
- ) {
156
- return (methodMirror: MethodMirror) => {
157
- // If the Apex method receives parameters, they will be interpreted by Salesforce as a JSON
158
- // object, with each key of the object being the parameter name.
159
- const parameters = methodMirror.parameters;
160
-
161
- if (!parameters.length) {
162
- return;
163
- }
164
-
165
- const propertiesObject: PropertiesObject = {};
166
- parameters.forEach((currentParameter) => {
167
- const propertyKey = currentParameter.name;
168
- const propertyReference = new ReferenceBuilder().getReferenceType(currentParameter.typeReference);
169
-
170
- propertiesObject[propertyKey] = propertyReference.schema;
171
-
172
- this.addReference({
173
- reference: {
174
- entrypointReferenceObject: propertyReference.schema as ReferenceObject,
175
- referenceComponents: propertyReference.referenceComponents,
176
- },
177
- });
178
- });
179
-
180
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.requestBody = {
181
- content: {
182
- 'application/json': {
183
- schema: {
184
- type: 'object',
185
- properties: propertiesObject,
186
- },
187
- },
188
- },
189
- };
190
- };
191
- }
192
-
193
- private getFallbackHttpResponseParser(
194
- httpUrlEndpoint: string,
195
- httpMethodKey: 'get' | 'put' | 'post' | 'delete' | 'patch',
196
- ) {
197
- return (methodMirror: MethodMirror) => {
198
- // Parses methods that return an object (as opposed to void).
199
- const returnType = methodMirror.typeReference;
200
-
201
- if (returnType.type.toLowerCase() === 'void') {
202
- return;
203
- }
204
-
205
- const reference = new ReferenceBuilder().getReferenceType(returnType);
206
-
207
- this.addReference({
208
- reference: {
209
- entrypointReferenceObject: reference.schema as ReferenceObject,
210
- referenceComponents: reference.referenceComponents,
211
- },
212
- });
213
-
214
- if (this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses === undefined) {
215
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses = {};
216
- }
217
-
218
- // Successful responses with a non-void return type always return a status code of 2000
219
- this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses!['200'] = {
220
- description: methodMirror.docComment?.description ?? 'Status code 200',
221
- content: {
222
- 'application/json': { schema: reference.schema },
223
- },
224
- };
225
- };
226
- }
227
-
228
- private addReference(referenceHolder: { reference?: Reference }): void {
229
- if (referenceHolder.reference) {
230
- // If a reference is returned, we want to make sure to add it to the OpenApi object as well
231
- // Add to "component" section if it hasn't been already
232
- if (this.openApiModel.components === undefined) {
233
- this.openApiModel.components = {
234
- schemas: {},
235
- };
236
- }
237
-
238
- if (!referenceHolder.reference.referenceComponents.length) {
239
- return;
240
- }
241
-
242
- // Add all received references to the OpenApi components section.
243
- referenceHolder.reference.referenceComponents.forEach((current) => {
244
- // Check if the referenced object is already part of the OpenApi object
245
- this.openApiModel.components!.schemas![current.referencedClass] = current.schema;
246
- });
247
- }
248
- }
249
- }
@@ -1,13 +0,0 @@
1
- import { ParameterObject } from '../../../core/openapi/open-api-types';
2
- import { Reference } from './ReferenceBuilder';
3
- import { ApexDocParameterObject } from '../../../core/openapi/apex-doc-types';
4
- import { Builder } from './Builder';
5
-
6
- export class ParameterObjectBuilder extends Builder<ParameterObject, ApexDocParameterObject> {
7
- buildBody(apexDocObject: ApexDocParameterObject, reference?: Reference): ParameterObject {
8
- return {
9
- ...apexDocObject,
10
- schema: this.getOpenApiSchemaFromApexDocSchema(apexDocObject, reference),
11
- };
12
- }
13
- }
@@ -1,299 +0,0 @@
1
- import * as yaml from 'js-yaml';
2
- import {
3
- PropertiesObject,
4
- ReferenceObject,
5
- SchemaObject,
6
- SchemaObjectArray,
7
- SchemaObjectObject,
8
- } from '../../../core/openapi/open-api-types';
9
- import { TypeBundle, TypesRepository } from '../../../core/openapi/types-repository';
10
- import { ClassMirror, DocCommentAnnotation, FieldMirror, PropertyMirror } from '@cparra/apex-reflection';
11
- import { ListObjectType, ReferencedType } from '@cparra/apex-reflection';
12
- import { ApexDocSchemaObject } from '../../../core/openapi/apex-doc-types';
13
-
14
- type TypeBundleWithIsCollectionAndReferenceOverrides = TypeBundle & {
15
- originalTypeName: string;
16
- isCollection: boolean;
17
- referenceOverrides: ReferenceOverride[];
18
- };
19
-
20
- export class ReferenceBuilder {
21
- build(referencedTypeName: string): Reference {
22
- const originalTypeName = referencedTypeName;
23
-
24
- // Checking for inline overrides of the type: [memberName:ClassOverrideName]
25
- const regexForSchemaOverrides = /\[(.*?)]/g;
26
- const schemaOverrides = referencedTypeName.match(regexForSchemaOverrides);
27
- let referenceOverrides: ReferenceOverride[] = [];
28
- if (schemaOverrides && schemaOverrides.length > 0) {
29
- referenceOverrides = ReferenceOverrides.build(schemaOverrides[0]);
30
- referencedTypeName = referencedTypeName.replace(regexForSchemaOverrides, '');
31
- }
32
-
33
- const [parsedReferencedType, isCollection] = this.handlePossibleCollectionReference(referencedTypeName);
34
- const referencedTypeBundle = TypesRepository.getInstance().getFromAllByName(parsedReferencedType);
35
-
36
- if (!referencedTypeBundle) {
37
- throw new Error(`The referenced type ${referencedTypeName} was not found.`);
38
- }
39
- if (referencedTypeBundle.type.type_name !== 'class') {
40
- throw new Error(
41
- `Expected the referenced type to be a class, but found a ${referencedTypeBundle.type.type_name}.`,
42
- );
43
- }
44
- const typeBundleWithIsCollection = {
45
- ...referencedTypeBundle,
46
- originalTypeName: originalTypeName,
47
- isCollection: isCollection,
48
- referenceOverrides: referenceOverrides,
49
- };
50
- return this.buildReferenceFromType(typeBundleWithIsCollection);
51
- }
52
-
53
- /**
54
- * Returns a tuple where the first value is the name of the reference without any collection related values
55
- * and the second is a boolean representing if we are dealing with a collection or not.
56
- * @param referencedTypeName The received raw type name.
57
- * @private
58
- */
59
- private handlePossibleCollectionReference(referencedTypeName: string): [string, boolean] {
60
- referencedTypeName = referencedTypeName.toLowerCase();
61
- if (referencedTypeName.startsWith('list<') && referencedTypeName.endsWith('>')) {
62
- referencedTypeName = referencedTypeName.replace('list<', '');
63
- referencedTypeName = referencedTypeName.replace('>', '');
64
- return [referencedTypeName, true];
65
- }
66
- if (referencedTypeName.startsWith('set<') && referencedTypeName.endsWith('>')) {
67
- referencedTypeName = referencedTypeName.replace('set<', '');
68
- referencedTypeName = referencedTypeName.replace('>', '');
69
- return [referencedTypeName, true];
70
- }
71
- return [referencedTypeName, false];
72
- }
73
-
74
- private buildReferenceFromType(typeBundle: TypeBundleWithIsCollectionAndReferenceOverrides): Reference {
75
- // Filtering based on Salesforce's documentation:
76
- // https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest_methods.htm#ApexRESTUserDefinedTypes
77
- // We assume that the class only contains object types allowed by Apex Rest:
78
- // "Note that the public, private, or global class member variables must be types allowed by Apex REST"
79
- const propertiesAndFields: (FieldMirror | PropertyMirror)[] = [
80
- ...(typeBundle.type as ClassMirror).properties,
81
- ...(typeBundle.type as ClassMirror).fields,
82
- ]
83
- .filter((current) => !current.memberModifiers.includes('static'))
84
- .filter((current) => !current.memberModifiers.includes('transient'));
85
-
86
- const properties: PropertiesObject = {};
87
- let referencedComponents: ReferenceComponent[] = [];
88
- propertiesAndFields.forEach((current) => {
89
- // Check if there are reference overrides for the current property, this takes priority over anything else.
90
- const referenceOverride = typeBundle.referenceOverrides.find((currentOverride) => {
91
- return currentOverride.propertyName.toLowerCase() === current.name.toLowerCase();
92
- });
93
- if (referenceOverride) {
94
- const reference = this.build(referenceOverride.referenceName);
95
- properties[current.name] = reference.entrypointReferenceObject;
96
- reference.referenceComponents.forEach((current) => referencedComponents.push(current));
97
- } else {
98
- // Check for "@http-schema" annotations within properties themselves. If these are specified they
99
- // take precedence over the property type itself.
100
- const manuallyDefinedHttpSchema = current.docComment?.annotations.find(
101
- (annotation) => annotation.name.toLowerCase() === 'http-schema',
102
- );
103
- if (manuallyDefinedHttpSchema) {
104
- this.handleOverriddenSchema(manuallyDefinedHttpSchema, properties, current, referencedComponents);
105
- } else {
106
- const pair = this.getReferenceType(current.typeReference);
107
- properties[current.name] = pair.schema;
108
- referencedComponents.push(...pair.referenceComponents);
109
- }
110
- }
111
-
112
- properties[current.name].description = current.docComment?.description;
113
- });
114
- const mainReferenceComponents = this.buildMainReferenceComponent(typeBundle, properties);
115
-
116
- // Make sure to add the "main" reference first
117
- referencedComponents = [...mainReferenceComponents, ...referencedComponents];
118
-
119
- return {
120
- entrypointReferenceObject: {
121
- $ref: `#/components/schemas/${this.getReferenceName(typeBundle)}`,
122
- },
123
- referenceComponents: referencedComponents,
124
- };
125
- }
126
-
127
- private handleOverriddenSchema(
128
- manuallyDefinedHttpSchema: DocCommentAnnotation,
129
- properties: PropertiesObject,
130
- current: FieldMirror | PropertyMirror,
131
- referencedComponents: ReferenceComponent[],
132
- ) {
133
- // This can be of type ApexDocSchemaObject
134
- const inYaml = manuallyDefinedHttpSchema?.bodyLines.reduce((prev, current) => prev + '\n' + current);
135
- const asJson = yaml.load(inYaml) as ApexDocSchemaObject;
136
- const isReferenceString = this.isReferenceString(asJson);
137
-
138
- if (isReferenceString) {
139
- const reference = this.build(asJson);
140
- properties[current.name] = reference.entrypointReferenceObject;
141
- reference.referenceComponents.forEach((current) => referencedComponents.push(current));
142
- } else {
143
- // If we are dealing with a manually defined schema object, we can add it directly to the "properties" map,
144
- // because we don't need to add a reference component.
145
- properties[current.name] = asJson;
146
- }
147
- }
148
-
149
- private getReferenceName(typeBundle: TypeBundleWithIsCollectionAndReferenceOverrides): string {
150
- let referenceName = typeBundle.type.name;
151
- if (typeBundle.isChild) {
152
- referenceName = `${typeBundle.parentType?.name}.${typeBundle.type.name}`;
153
- }
154
- if (typeBundle.isCollection) {
155
- referenceName = `${referenceName}_array`;
156
- }
157
- if (typeBundle.referenceOverrides.length) {
158
- referenceName = `${referenceName}_${typeBundle.originalTypeName}`;
159
- }
160
- return referenceName;
161
- }
162
-
163
- private buildMainReferenceComponent(
164
- typeBundle: TypeBundleWithIsCollectionAndReferenceOverrides,
165
- properties: PropertiesObject,
166
- ): ReferenceComponent[] {
167
- // For the main reference, we always want to get the reference of the object without the collection part,
168
- // so we pass the typeBundle to `getReferenceName` but with the isCollection flag set to false.
169
- const mainReferenceName = this.getReferenceName({ ...typeBundle, isCollection: false });
170
- const mainReference: ReferenceComponent = {
171
- referencedClass: mainReferenceName,
172
- schema: {
173
- type: 'object',
174
- properties: properties,
175
- },
176
- };
177
- const referencedComponents = [mainReference];
178
- if (!typeBundle.isCollection) {
179
- return referencedComponents;
180
- }
181
-
182
- return [
183
- {
184
- referencedClass: this.getReferenceName(typeBundle),
185
- schema: {
186
- type: 'array',
187
- items: {
188
- $ref: `#/components/schemas/${mainReferenceName}`,
189
- },
190
- },
191
- },
192
- ...referencedComponents,
193
- ];
194
- }
195
-
196
- public getReferenceType(typeInMirror: ReferencedType): SchemaObjectReferencePair {
197
- // Returns a valid type supported by OpenApi from a received Apex type.
198
- const typeName = typeInMirror.type.toLowerCase();
199
- switch (typeName) {
200
- case 'boolean':
201
- return { schema: { type: 'boolean' }, referenceComponents: [] };
202
- case 'date':
203
- return { schema: { type: 'string', format: 'date' }, referenceComponents: [] };
204
- case 'datetime':
205
- return { schema: { type: 'string', format: 'date-time' }, referenceComponents: [] };
206
- case 'decimal':
207
- return { schema: { type: 'number' }, referenceComponents: [] };
208
- case 'double':
209
- return { schema: { type: 'number' }, referenceComponents: [] };
210
- case 'id':
211
- return { schema: { type: 'string' }, referenceComponents: [] };
212
- case 'integer':
213
- return { schema: { type: 'integer' }, referenceComponents: [] };
214
- case 'long':
215
- return { schema: { type: 'integer', format: 'int64' }, referenceComponents: [] };
216
- case 'string':
217
- return { schema: { type: 'string' }, referenceComponents: [] };
218
- case 'time':
219
- return { schema: { type: 'string', format: 'time' }, referenceComponents: [] };
220
- case 'list':
221
- return this.buildCollectionPair(typeInMirror);
222
- case 'set':
223
- return this.buildCollectionPair(typeInMirror);
224
- case 'map':
225
- // For Maps, we treat them as objects but do not try to define their shape, because their keys can vary
226
- // at runtime.
227
- return { schema: { type: 'object' }, referenceComponents: [] };
228
- case 'object':
229
- return { schema: { type: 'object' }, referenceComponents: [] };
230
- default: {
231
- // If we got here we are dealing with a non-primitive (most likely a custom class or an SObject).
232
- const referencedType = TypesRepository.getInstance().getFromAllByName(typeName);
233
- if (!referencedType) {
234
- return { schema: { type: 'object' }, referenceComponents: [] };
235
- }
236
- const reference = this.buildReferenceFromType({
237
- ...referencedType,
238
- isCollection: false,
239
- referenceOverrides: [],
240
- originalTypeName: typeName,
241
- });
242
- return {
243
- schema: reference.entrypointReferenceObject,
244
- referenceComponents: [...reference.referenceComponents],
245
- };
246
- }
247
- }
248
- }
249
-
250
- private buildCollectionPair(typeInMirror: ReferencedType) {
251
- const innerReference = this.getReferenceType((typeInMirror as ListObjectType).ofType);
252
- return {
253
- schema: { type: 'array', items: innerReference.schema },
254
- referenceComponents: [...innerReference.referenceComponents],
255
- };
256
- }
257
-
258
- private isReferenceString = (targetObject: unknown): targetObject is string => {
259
- return typeof targetObject === 'string' || targetObject instanceof String;
260
- };
261
- }
262
-
263
- type SchemaObjectReferencePair = {
264
- schema: SchemaObject;
265
- referenceComponents: ReferenceComponent[];
266
- };
267
-
268
- class ReferenceOverrides {
269
- static build(referenceAsString: string): ReferenceOverride[] {
270
- const cleanedUpReference = referenceAsString.replace(/[[\]]/g, '');
271
- const referenceStrings = cleanedUpReference.split(',').map((item) => item.replace(/\s/g, ''));
272
- return referenceStrings.map((item) => {
273
- const [propertyName, referenceName] = item.split(':');
274
- return { propertyName, referenceName };
275
- });
276
- }
277
- }
278
-
279
- type ReferenceOverride = {
280
- propertyName: string;
281
- referenceName: string;
282
- };
283
-
284
- /**
285
- * In case where the Request Body contains a reference, this contains information about the handled reference
286
- */
287
- export type Reference = {
288
- /** OpenApi style reference object for the parent caller */
289
- entrypointReferenceObject: ReferenceObject;
290
- /** List of objects that contain all component references identified by a call to this builder **/
291
- referenceComponents: ReferenceComponent[];
292
- };
293
-
294
- export type ReferenceComponent = {
295
- /** Name of the class being referenced */
296
- referencedClass: string;
297
- /** Parsed representation of the referenced object as an OpenApi Schema object */
298
- schema: SchemaObjectObject | SchemaObjectArray;
299
- };
@@ -1,19 +0,0 @@
1
- import { RequestBody } from '../../../core/openapi/open-api-types';
2
- import { Reference } from './ReferenceBuilder';
3
- import { ApexDocHttpRequestBody } from '../../../core/openapi/apex-doc-types';
4
- import { Builder } from './Builder';
5
-
6
- /**
7
- * Parses and builds OpenApi Request Body objects.
8
- */
9
- export class RequestBodyBuilder extends Builder<RequestBody, ApexDocHttpRequestBody> {
10
- buildBody(apexRequestBody: ApexDocHttpRequestBody, reference?: Reference): RequestBody {
11
- return {
12
- description: apexRequestBody.description,
13
- content: {
14
- 'application/json': { schema: this.getOpenApiSchemaFromApexDocSchema(apexRequestBody, reference) },
15
- },
16
- required: apexRequestBody.required,
17
- };
18
- }
19
- }
@@ -1,21 +0,0 @@
1
- import { ResponseObject } from '../../../core/openapi/open-api-types';
2
- import { Reference } from './ReferenceBuilder';
3
- import { ApexDocHttpResponse } from '../../../core/openapi/apex-doc-types';
4
- import { Builder } from './Builder';
5
-
6
- export class ResponsesBuilder extends Builder<ResponseObject, ApexDocHttpResponse> {
7
- buildBody(apexDocResponseDefinition: ApexDocHttpResponse, reference?: Reference): ResponseObject {
8
- let description = `Status code ${apexDocResponseDefinition.statusCode}`;
9
- if (apexDocResponseDefinition.description) {
10
- description = apexDocResponseDefinition.description;
11
- }
12
- return {
13
- description: description,
14
- content: {
15
- 'application/json': {
16
- schema: this.getOpenApiSchemaFromApexDocSchema(apexDocResponseDefinition, reference),
17
- },
18
- },
19
- };
20
- }
21
- }
@@ -1,44 +0,0 @@
1
- import { ClassMirrorBuilder } from '../../../../test-helpers/ClassMirrorBuilder';
2
- import { MethodMirrorBuilder } from '../../../../test-helpers/MethodMirrorBuilder';
3
- import { AnnotationBuilder } from '../../../../test-helpers/AnnotationBuilder';
4
- import { OpenApi } from '../../../../core/openapi/open-api';
5
- import { MethodParser } from '../MethodParser';
6
- import { DocCommentBuilder } from '../../../../test-helpers/DocCommentBuilder';
7
-
8
- it('should add an endpoint when there is an HTTP method', function () {
9
- const urlEndpoint = '/accounts';
10
-
11
- const classWithGetMethod = new ClassMirrorBuilder()
12
- .addMethod(new MethodMirrorBuilder().addAnnotation(new AnnotationBuilder().withName('httpget').build()).build())
13
- .build();
14
-
15
- const openApi = new OpenApi('Title', '1.0');
16
- openApi.paths[urlEndpoint] = {};
17
-
18
- expect(openApi.paths[urlEndpoint]).not.toHaveProperty('get');
19
-
20
- new MethodParser(openApi).parseMethod(classWithGetMethod, urlEndpoint, 'get', '');
21
-
22
- expect(openApi.paths[urlEndpoint]).toHaveProperty('get');
23
- });
24
-
25
- it('should add an endpoint with a description when the method has an ApexDoc', function () {
26
- const urlEndpoint = '/accounts';
27
-
28
- const classWithGetMethod = new ClassMirrorBuilder()
29
- .addMethod(
30
- new MethodMirrorBuilder()
31
- .addAnnotation(new AnnotationBuilder().withName('httpget').build())
32
- .withDocComment(new DocCommentBuilder().withDescription('Sample Description').build())
33
- .build(),
34
- )
35
- .build();
36
-
37
- const openApi = new OpenApi('Title', '1.0');
38
- openApi.paths[urlEndpoint] = {};
39
-
40
- new MethodParser(openApi).parseMethod(classWithGetMethod, urlEndpoint, 'get', '');
41
-
42
- expect(openApi.paths[urlEndpoint]).toHaveProperty('get');
43
- expect(openApi.paths[urlEndpoint]['get']!.description).toBe('Sample Description');
44
- });