@cparra/apexdocs 2.9.0 → 2.11.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 (81) hide show
  1. package/README.md +111 -66
  2. package/docs/Main/nspc.GroupedClass.md +10 -0
  3. package/docs/Main/{SampleClass.md → nspc.SampleClass.md} +21 -18
  4. package/docs/Misc-Group/nspc.AnotherInterface.md +1 -0
  5. package/docs/Misc-Group/{ChildClass.md → nspc.ChildClass.md} +4 -4
  6. package/docs/Misc-Group/{GrandparentClass.md → nspc.GrandparentClass.md} +1 -1
  7. package/docs/Misc-Group/{InterfaceWithInheritance.md → nspc.InterfaceWithInheritance.md} +3 -3
  8. package/docs/Misc-Group/nspc.MemberGrouping.md +13 -0
  9. package/docs/Misc-Group/{ParentClass.md → nspc.ParentClass.md} +2 -2
  10. package/docs/Misc-Group/{Reference1.md → nspc.Reference1.md} +1 -1
  11. package/docs/Misc-Group/nspc.Reference2.md +12 -0
  12. package/docs/Misc-Group/{Reference3.md → nspc.Reference3.md} +1 -1
  13. package/docs/Misc-Group/{Reference4.md → nspc.Reference4.md} +1 -1
  14. package/docs/Misc-Group/{Reference5.md → nspc.Reference5.md} +1 -1
  15. package/docs/Misc-Group/{Reference6.md → nspc.Reference6.md} +1 -1
  16. package/docs/Misc-Group/{SampleClassWithoutModifier.md → nspc.SampleClassWithoutModifier.md} +1 -1
  17. package/docs/Misc-Group/{SampleRestResource.md → nspc.SampleRestResource.md} +1 -4
  18. package/docs/Misc-Group/{SampleRestResourceWithInnerClass.md → nspc.SampleRestResourceWithInnerClass.md} +1 -1
  19. package/docs/Misc-Group/nspc.SampleRestResourceWithoutApexDocs.md +14 -0
  20. package/docs/README.md +28 -19
  21. package/docs/Sample-Interfaces/{SampleInterface.md → nspc.SampleInterface.md} +1 -1
  22. package/docs/index.html +22 -22
  23. package/docs/{openapi.json → restapi.json} +77 -13
  24. package/examples/force-app/main/default/classes/MemberGrouping.cls +16 -0
  25. package/examples/force-app/main/default/classes/SampleClass.cls +3 -0
  26. package/examples/force-app/main/default/restapi/SampleRestResource.cls +0 -4
  27. package/examples/force-app/main/default/restapi/SampleRestResourceWithoutApexDocs.cls +15 -0
  28. package/examples/force-app/main/default/restapi/references/Reference2.cls +6 -0
  29. package/lib/cli/generate.js +12 -0
  30. package/lib/cli/generate.js.map +1 -1
  31. package/lib/model/markdown-generation-util/field-declaration-util.js +6 -1
  32. package/lib/model/markdown-generation-util/field-declaration-util.js.map +1 -1
  33. package/lib/model/markdown-type-file.d.ts +4 -3
  34. package/lib/model/markdown-type-file.js +21 -7
  35. package/lib/model/markdown-type-file.js.map +1 -1
  36. package/lib/model/openapi/open-api.d.ts +1 -1
  37. package/lib/model/openapi/open-api.js.map +1 -1
  38. package/lib/model/openapi/openapi-type-file.js +3 -2
  39. package/lib/model/openapi/openapi-type-file.js.map +1 -1
  40. package/lib/settings.d.ts +5 -0
  41. package/lib/settings.js +12 -0
  42. package/lib/settings.js.map +1 -1
  43. package/lib/test-helpers/DocCommentAnnotationBuilder.d.ts +2 -0
  44. package/lib/test-helpers/DocCommentAnnotationBuilder.js +6 -1
  45. package/lib/test-helpers/DocCommentAnnotationBuilder.js.map +1 -1
  46. package/lib/test-helpers/FieldMirrorBuilder.d.ts +3 -1
  47. package/lib/test-helpers/FieldMirrorBuilder.js +6 -0
  48. package/lib/test-helpers/FieldMirrorBuilder.js.map +1 -1
  49. package/lib/test-helpers/SettingsBuilder.js +1 -0
  50. package/lib/test-helpers/SettingsBuilder.js.map +1 -1
  51. package/lib/transpiler/markdown/class-file-generatorHelper.js +2 -1
  52. package/lib/transpiler/markdown/class-file-generatorHelper.js.map +1 -1
  53. package/lib/transpiler/openapi/open-api-docs-processor.d.ts +1 -0
  54. package/lib/transpiler/openapi/open-api-docs-processor.js +4 -2
  55. package/lib/transpiler/openapi/open-api-docs-processor.js.map +1 -1
  56. package/lib/transpiler/openapi/parsers/MethodParser.d.ts +3 -0
  57. package/lib/transpiler/openapi/parsers/MethodParser.js +80 -19
  58. package/lib/transpiler/openapi/parsers/MethodParser.js.map +1 -1
  59. package/lib/transpiler/openapi/parsers/ReferenceBuilder.d.ts +10 -2
  60. package/lib/transpiler/openapi/parsers/ReferenceBuilder.js +35 -5
  61. package/lib/transpiler/openapi/parsers/ReferenceBuilder.js.map +1 -1
  62. package/package.json +5 -5
  63. package/src/cli/generate.ts +13 -0
  64. package/src/model/markdown-generation-util/field-declaration-util.ts +8 -3
  65. package/src/model/markdown-type-file.ts +25 -9
  66. package/src/model/openapi/open-api.ts +1 -1
  67. package/src/model/openapi/openapi-type-file.ts +3 -2
  68. package/src/service/__tests__/apex-file-reader.spec.ts +1 -0
  69. package/src/settings.ts +17 -0
  70. package/src/test-helpers/DocCommentAnnotationBuilder.ts +7 -1
  71. package/src/test-helpers/FieldMirrorBuilder.ts +8 -1
  72. package/src/test-helpers/SettingsBuilder.ts +1 -0
  73. package/src/transpiler/markdown/class-file-generatorHelper.ts +2 -1
  74. package/src/transpiler/openapi/open-api-docs-processor.ts +4 -2
  75. package/src/transpiler/openapi/parsers/MethodParser.ts +134 -30
  76. package/src/transpiler/openapi/parsers/ReferenceBuilder.ts +42 -6
  77. package/src/transpiler/openapi/parsers/__tests__/ReferenceBuilder.spec.ts +85 -0
  78. package/docs/API/SampleClassWithoutModifier.md +0 -11
  79. package/docs/Main/GroupedClass.md +0 -10
  80. package/docs/Misc-Group/AnotherInterface.md +0 -1
  81. package/docs/Misc-Group/Reference2.md +0 -7
@@ -16,6 +16,7 @@ export class SettingsBuilder {
16
16
  defaultGroupName: 'Misc',
17
17
  sanitizeHtml: true,
18
18
  openApiTitle: 'Apex API',
19
+ openApiFileName: 'openapi',
19
20
  };
20
21
  }
21
22
  }
@@ -11,7 +11,8 @@ export default class ClassFileGeneratorHelper {
11
11
 
12
12
  public static getFileLink(classModel: Type) {
13
13
  const directoryRoot = this.getDirectoryRoot(classModel);
14
- return `[${classModel.name}](${directoryRoot}${classModel.name}.md)`;
14
+ const fullClassName = `${Settings.getInstance().getNamespacePrefix()}${classModel.name}`;
15
+ return `[${fullClassName}](${directoryRoot}${fullClassName}.md)`;
15
16
  }
16
17
 
17
18
  public static getFileLinkByTypeName(typeName: string) {
@@ -18,7 +18,7 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
18
18
  if (!title) {
19
19
  throw Error('No OpenApi title was provided.');
20
20
  }
21
- this.openApiModel = new OpenApi(title, '1.0.0');
21
+ this.openApiModel = new OpenApi(title, '1.0.0', Settings.getInstance().getNamespace());
22
22
  }
23
23
 
24
24
  fileBuilder(): FileContainer {
@@ -57,9 +57,11 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
57
57
 
58
58
  // DELETE
59
59
  parser.parseMethod(typeAsClass, endpointPath, 'delete');
60
+ }
60
61
 
62
+ onAfterProcess: ((types: Type[]) => void) | undefined = () => {
61
63
  this._fileContainer.pushFile(new OpenapiTypeFile(this.openApiModel));
62
- }
64
+ };
63
65
 
64
66
  private getEndpointPath(type: Type): string | null {
65
67
  const restResourceAnnotation = type.annotations.find((element) => element.name.toLowerCase() === 'restresource');
@@ -2,7 +2,7 @@ import { ClassMirror, MethodMirror } from '@cparra/apex-reflection';
2
2
  import { OpenApi } from '../../../model/openapi/open-api';
3
3
  import * as yaml from 'js-yaml';
4
4
  import { ClassMirrorWrapper } from '../../../model/apex-type-wrappers/ClassMirrorWrapper';
5
- import { Reference } from './ReferenceBuilder';
5
+ import { Reference, ReferenceBuilder } from './ReferenceBuilder';
6
6
  import { ParameterObjectBuilder } from './ParameterObjectBuilder';
7
7
  import { ResponsesBuilder } from './ResponsesBuilder';
8
8
  import {
@@ -11,8 +11,11 @@ import {
11
11
  ApexDocParameterObject,
12
12
  } from '../../../model/openapi/apex-doc-types';
13
13
  import { RequestBodyBuilder } from './RequestBodyBuilder';
14
+ import { ApexDocSchemaAware } from './Builder';
15
+ import { PropertiesObject, ReferenceObject } from '../../../model/openapi/open-api-types';
14
16
 
15
- type AddToOpenApi = (inYaml: string, urlValue: string) => void;
17
+ type FallbackMethodParser = (methodMirror: MethodMirror) => void;
18
+ type AddToOpenApi<T extends ApexDocSchemaAware> = (input: T, urlValue: string, httpMethodKey: HttpOperations) => void;
16
19
 
17
20
  type HttpOperations = 'get' | 'put' | 'post' | 'delete' | 'patch';
18
21
 
@@ -39,28 +42,47 @@ export class MethodParser {
39
42
  this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.description = httpMethod.docComment.description;
40
43
  }
41
44
 
42
- this.parseHttpAnnotation(httpMethod, httpUrlEndpoint, 'http-request-body', (inYaml, urlValue) =>
43
- this.addRequestBodyToOpenApi(inYaml, urlValue, httpMethodKey),
45
+ this.parseHttpAnnotation<ApexDocHttpRequestBody>(
46
+ httpMethod,
47
+ httpUrlEndpoint,
48
+ httpMethodKey,
49
+ 'http-request-body',
50
+ this.addRequestBodyToOpenApi.bind(this),
51
+ this.fallbackHttpRequestBodyParser(httpUrlEndpoint, httpMethodKey),
44
52
  );
45
- this.parseHttpAnnotation(httpMethod, httpUrlEndpoint, 'http-parameter', (inYaml, urlValue) =>
46
- this.addParametersToOpenApi(inYaml, urlValue, httpMethodKey),
53
+
54
+ this.parseHttpAnnotation<ApexDocParameterObject>(
55
+ httpMethod,
56
+ httpUrlEndpoint,
57
+ httpMethodKey,
58
+ 'http-parameter',
59
+ this.addParametersToOpenApi.bind(this),
47
60
  );
48
- this.parseHttpAnnotation(httpMethod, httpUrlEndpoint, 'http-response', (inYaml, urlValue) =>
49
- this.addHttpResponsesToOpenApi(inYaml, urlValue, httpMethodKey),
61
+
62
+ this.parseHttpAnnotation<ApexDocHttpResponse>(
63
+ httpMethod,
64
+ httpUrlEndpoint,
65
+ httpMethodKey,
66
+ 'http-response',
67
+ this.addHttpResponsesToOpenApi.bind(this),
68
+ this.getFallbackHttpResponseParser(httpUrlEndpoint, httpMethodKey),
50
69
  );
51
70
  }
52
71
 
53
- private parseHttpAnnotation(
54
- httpGetMethod: MethodMirror,
72
+ private parseHttpAnnotation<T extends ApexDocSchemaAware>(
73
+ httpMethod: MethodMirror,
55
74
  urlValue: string,
75
+ httpMethodKey: HttpOperations,
56
76
  annotationName: string,
57
- addToOpenApi: AddToOpenApi,
77
+ addToOpenApi: AddToOpenApi<T>,
78
+ fallbackParser?: FallbackMethodParser,
58
79
  ) {
59
- const annotations = httpGetMethod.docComment?.annotations.filter(
60
- (annotation) => annotation.name === annotationName,
61
- );
80
+ const annotations = httpMethod.docComment?.annotations.filter((annotation) => annotation.name === annotationName);
62
81
 
63
82
  if (!annotations?.length) {
83
+ if (fallbackParser) {
84
+ fallbackParser(httpMethod);
85
+ }
64
86
  return;
65
87
  }
66
88
 
@@ -72,46 +94,128 @@ export class MethodParser {
72
94
  return;
73
95
  }
74
96
 
75
- addToOpenApi(inYaml, urlValue);
97
+ this.addToOpenApiStrategy<T>(inYaml, urlValue, httpMethodKey, addToOpenApi);
76
98
  }
77
99
  }
78
100
 
79
- private addRequestBodyToOpenApi(inYaml: string, urlValue: string, httpMethodKey: HttpOperations) {
101
+ private addToOpenApiStrategy<T extends ApexDocSchemaAware>(
102
+ inYaml: string,
103
+ urlValue: string,
104
+ httpMethodKey: HttpOperations,
105
+ addToOpenApi: AddToOpenApi<T>,
106
+ ): void {
80
107
  // Convert the YAML into a JSON object.
81
- const inJson = yaml.load(inYaml) as ApexDocHttpRequestBody;
108
+ const inJson = yaml.load(inYaml) as T;
82
109
  const requestBodyResponse = new RequestBodyBuilder().build(inJson);
83
110
 
84
- this.openApiModel.paths[urlValue][httpMethodKey]!.requestBody = requestBodyResponse.body;
111
+ addToOpenApi(inJson, urlValue, httpMethodKey);
85
112
 
86
113
  this.addReference(requestBodyResponse);
87
114
  }
88
115
 
89
- private addParametersToOpenApi(inYaml: string, urlValue: string, httpMethodKey: HttpOperations) {
90
- // Convert the YAML into a JSON object.
91
- const inJson = yaml.load(inYaml) as ApexDocParameterObject;
92
- const parameterObjectResponse = new ParameterObjectBuilder().build(inJson);
116
+ private addRequestBodyToOpenApi(
117
+ input: ApexDocHttpRequestBody,
118
+ urlValue: string,
119
+ httpMethodKey: HttpOperations,
120
+ ): void {
121
+ const requestBodyResponse = new RequestBodyBuilder().build(input);
122
+ this.openApiModel.paths[urlValue][httpMethodKey]!.requestBody = requestBodyResponse.body;
123
+ }
124
+
125
+ private addParametersToOpenApi(input: ApexDocParameterObject, urlValue: string, httpMethodKey: HttpOperations): void {
126
+ const parameterObjectResponse = new ParameterObjectBuilder().build(input);
93
127
 
94
128
  if (this.openApiModel.paths[urlValue][httpMethodKey]!.parameters === undefined) {
95
129
  // If no parameters have been defined yet, initialize the list.
96
130
  this.openApiModel.paths[urlValue][httpMethodKey]!.parameters = [];
97
131
  }
98
132
  this.openApiModel.paths[urlValue][httpMethodKey]!.parameters!.push(parameterObjectResponse.body);
99
-
100
- this.addReference(parameterObjectResponse);
101
133
  }
102
134
 
103
- private addHttpResponsesToOpenApi(inYaml: string, urlValue: string, httpMethodKey: HttpOperations) {
104
- // Convert the YAML into a JSON object.
105
- const inJson = yaml.load(inYaml) as ApexDocHttpResponse;
106
- const responseObjectResponse = new ResponsesBuilder().build(inJson);
135
+ private addHttpResponsesToOpenApi(input: ApexDocHttpResponse, urlValue: string, httpMethodKey: HttpOperations): void {
136
+ const responseObjectResponse = new ResponsesBuilder().build(input);
107
137
 
108
138
  if (this.openApiModel.paths[urlValue][httpMethodKey]!.responses === undefined) {
109
139
  this.openApiModel.paths[urlValue][httpMethodKey]!.responses = {};
110
140
  }
111
141
 
112
- this.openApiModel.paths[urlValue][httpMethodKey]!.responses![inJson.statusCode] = responseObjectResponse.body;
142
+ this.openApiModel.paths[urlValue][httpMethodKey]!.responses![input.statusCode] = responseObjectResponse.body;
143
+ }
144
+
145
+ private fallbackHttpRequestBodyParser(
146
+ httpUrlEndpoint: string,
147
+ httpMethodKey: 'get' | 'put' | 'post' | 'delete' | 'patch',
148
+ ) {
149
+ return (methodMirror: MethodMirror) => {
150
+ // If the Apex method receives parameters, they will be interpreted by Salesforce as a JSON
151
+ // object, with each key of the object being the parameter name.
152
+ const parameters = methodMirror.parameters;
153
+
154
+ if (!parameters.length) {
155
+ return;
156
+ }
157
+
158
+ const propertiesObject: PropertiesObject = {};
159
+ parameters.forEach((currentParameter) => {
160
+ const propertyKey = currentParameter.name;
161
+ const propertyReference = new ReferenceBuilder().getReferenceType(currentParameter.typeReference);
162
+
163
+ propertiesObject[propertyKey] = propertyReference.schema;
164
+
165
+ this.addReference({
166
+ reference: {
167
+ entrypointReferenceObject: propertyReference.schema as ReferenceObject,
168
+ referenceComponents: propertyReference.referenceComponents,
169
+ },
170
+ });
171
+ });
172
+
173
+ this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.requestBody = {
174
+ content: {
175
+ 'application/json': {
176
+ schema: {
177
+ type: 'object',
178
+ properties: propertiesObject,
179
+ },
180
+ },
181
+ },
182
+ };
183
+ };
184
+ }
185
+
186
+ private getFallbackHttpResponseParser(
187
+ httpUrlEndpoint: string,
188
+ httpMethodKey: 'get' | 'put' | 'post' | 'delete' | 'patch',
189
+ ) {
190
+ return (methodMirror: MethodMirror) => {
191
+ // Parses methods that return an object (as opposed to void).
192
+ const returnType = methodMirror.typeReference;
193
+
194
+ if (returnType.type.toLowerCase() === 'void') {
195
+ return;
196
+ }
197
+
198
+ const reference = new ReferenceBuilder().getReferenceType(returnType);
199
+
200
+ this.addReference({
201
+ reference: {
202
+ entrypointReferenceObject: reference.schema as ReferenceObject,
203
+ referenceComponents: reference.referenceComponents,
204
+ },
205
+ });
206
+
207
+ if (this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses === undefined) {
208
+ this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses = {};
209
+ }
113
210
 
114
- this.addReference(responseObjectResponse);
211
+ // Successful responses with a non-void return type always return a status code of 2000
212
+ this.openApiModel.paths[httpUrlEndpoint][httpMethodKey]!.responses!['200'] = {
213
+ description: methodMirror.docComment?.description ?? 'Status code 200',
214
+ content: {
215
+ 'application/json': { schema: reference.schema },
216
+ },
217
+ };
218
+ };
115
219
  }
116
220
 
117
221
  private addReference(referenceHolder: { reference?: Reference }): void {
@@ -1,3 +1,4 @@
1
+ import * as yaml from 'js-yaml';
1
2
  import {
2
3
  PropertiesObject,
3
4
  ReferenceObject,
@@ -6,8 +7,9 @@ import {
6
7
  SchemaObjectObject,
7
8
  } from '../../../model/openapi/open-api-types';
8
9
  import { TypeBundle, TypesRepository } from '../../../model/types-repository';
9
- import { ClassMirror, FieldMirror, PropertyMirror, Type } from '@cparra/apex-reflection';
10
+ import { ClassMirror, DocCommentAnnotation, FieldMirror, PropertyMirror } from '@cparra/apex-reflection';
10
11
  import { ListObjectType, ReferencedType } from '@cparra/apex-reflection/index';
12
+ import { ApexDocSchemaObject } from '../../../model/openapi/apex-doc-types';
11
13
 
12
14
  type TypeBundleWithIsCollection = TypeBundle & { isCollection: boolean };
13
15
 
@@ -64,12 +66,20 @@ export class ReferenceBuilder {
64
66
  const properties: PropertiesObject = {};
65
67
  let referencedComponents: ReferenceComponent[] = [];
66
68
  propertiesAndFields.forEach((current) => {
67
- const pair = this.getReferenceType(current.typeReference);
68
- properties[current.name] = pair.schema;
69
+ // Check for "@http-schema" annotations within properties themselves. If these are specified they
70
+ // take precedence over the property type itself.
71
+ const manuallyDefinedHttpSchema = current.docComment?.annotations.find(
72
+ (annotation) => annotation.name.toLowerCase() === 'http-schema',
73
+ );
74
+ if (manuallyDefinedHttpSchema) {
75
+ this.handleOverriddenSchema(manuallyDefinedHttpSchema, properties, current, referencedComponents);
76
+ } else {
77
+ const pair = this.getReferenceType(current.typeReference);
78
+ properties[current.name] = pair.schema;
79
+ pair.referenceComponents.forEach((current) => referencedComponents.push(current));
80
+ }
69
81
  properties[current.name].description = current.docComment?.description;
70
- pair.referenceComponents.forEach((current) => referencedComponents.push(current));
71
82
  });
72
-
73
83
  const mainReferenceComponents = this.buildMainReferenceComponent(typeBundle, properties);
74
84
 
75
85
  // Make sure to add the "main" reference first
@@ -83,6 +93,28 @@ export class ReferenceBuilder {
83
93
  };
84
94
  }
85
95
 
96
+ private handleOverriddenSchema(
97
+ manuallyDefinedHttpSchema: DocCommentAnnotation,
98
+ properties: PropertiesObject,
99
+ current: FieldMirror | PropertyMirror,
100
+ referencedComponents: ReferenceComponent[],
101
+ ) {
102
+ // This can be of type ApexDocSchemaObject
103
+ const inYaml = manuallyDefinedHttpSchema?.bodyLines.reduce((prev, current, _) => prev + '\n' + current);
104
+ const asJson = yaml.load(inYaml) as ApexDocSchemaObject;
105
+ const isReference = this.isReferenceString(asJson);
106
+
107
+ if (isReference) {
108
+ const reference = this.build(asJson);
109
+ properties[current.name] = reference.entrypointReferenceObject;
110
+ reference.referenceComponents.forEach((current) => referencedComponents.push(current));
111
+ } else {
112
+ // If we are dealing with a manually defined schema object, we can add it directly to the "properties" map,
113
+ // because we don't need to add a reference component.
114
+ properties[current.name] = asJson;
115
+ }
116
+ }
117
+
86
118
  private getReferenceName(typeBundle: TypeBundleWithIsCollection): string {
87
119
  let referenceName = typeBundle.type.name;
88
120
  if (typeBundle.isChild) {
@@ -127,7 +159,7 @@ export class ReferenceBuilder {
127
159
  ];
128
160
  }
129
161
 
130
- private getReferenceType(typeInMirror: ReferencedType): SchemaObjectReferencePair {
162
+ public getReferenceType(typeInMirror: ReferencedType): SchemaObjectReferencePair {
131
163
  // Returns a valid type supported by OpenApi from a received Apex type.
132
164
  const typeName = typeInMirror.type.toLowerCase();
133
165
  switch (typeName) {
@@ -180,6 +212,10 @@ export class ReferenceBuilder {
180
212
  referenceComponents: [...innerReference.referenceComponents],
181
213
  };
182
214
  }
215
+
216
+ private isReferenceString = (targetObject: any): targetObject is string => {
217
+ return typeof targetObject === 'string' || targetObject instanceof String;
218
+ };
183
219
  }
184
220
 
185
221
  type SchemaObjectReferencePair = {
@@ -3,6 +3,8 @@ import { ReferenceBuilder } from '../ReferenceBuilder';
3
3
  import { ClassMirrorBuilder } from '../../../../test-helpers/ClassMirrorBuilder';
4
4
  import { FieldMirrorBuilder } from '../../../../test-helpers/FieldMirrorBuilder';
5
5
  import { SchemaObjectArray, SchemaObjectObject } from '../../../../model/openapi/open-api-types';
6
+ import { DocCommentBuilder } from '../../../../test-helpers/DocCommentBuilder';
7
+ import { DocCommentAnnotationBuilder } from '../../../../test-helpers/DocCommentAnnotationBuilder';
6
8
 
7
9
  describe('ReferenceBuilder', () => {
8
10
  describe('Validation', () => {
@@ -619,4 +621,87 @@ describe('ReferenceBuilder', () => {
619
621
  expect((result.referenceComponents[1].schema as SchemaObjectObject).properties).toHaveProperty('fieldName');
620
622
  });
621
623
  });
624
+
625
+ describe('References can override their type', () => {
626
+ it("should correctly parse a manually defined schema in the reference's ApexDoc", function () {
627
+ const classMirror = new ClassMirrorBuilder()
628
+ .addFiled(
629
+ new FieldMirrorBuilder()
630
+ .withName('fieldName')
631
+ .withType('Object')
632
+ .withDocComment(
633
+ new DocCommentBuilder()
634
+ .addAnnotation(
635
+ new DocCommentAnnotationBuilder().withName('http-schema').withBodyLines(['type: string']).build(),
636
+ )
637
+ .build(),
638
+ )
639
+ .build(),
640
+ )
641
+ .build();
642
+
643
+ TypesRepository.getInstance = jest.fn().mockReturnValue({
644
+ getFromAllByName: jest.fn().mockReturnValue({ type: classMirror, isChild: false }),
645
+ });
646
+
647
+ const result = new ReferenceBuilder().build('className');
648
+
649
+ const schema = result.referenceComponents[0].schema as SchemaObjectObject;
650
+ expect(schema.properties).toHaveProperty('fieldName');
651
+ const fieldSchema = schema.properties!['fieldName'] as SchemaObjectObject;
652
+ expect(fieldSchema.type).toBe('string');
653
+ });
654
+
655
+ it('should correctly parse a manually defined reference while parsing properties', function () {
656
+ const mainClassMirror = new ClassMirrorBuilder()
657
+ .withName('parent')
658
+ .addFiled(
659
+ new FieldMirrorBuilder()
660
+ .withName('childClassMember')
661
+ .withType('Object')
662
+ .withDocComment(
663
+ new DocCommentBuilder()
664
+ .addAnnotation(
665
+ new DocCommentAnnotationBuilder().withName('http-schema').withBodyLines(['ChildClass']).build(),
666
+ )
667
+ .build(),
668
+ )
669
+ .build(),
670
+ )
671
+ .build();
672
+
673
+ const childClass = new ClassMirrorBuilder()
674
+ .withName('child')
675
+ .addFiled(
676
+ new FieldMirrorBuilder()
677
+ .withName('grandChildClassMember')
678
+ .withReferencedType({
679
+ type: 'GrandChildClass',
680
+ rawDeclaration: 'GrandChildClass',
681
+ })
682
+ .build(),
683
+ )
684
+ .build();
685
+
686
+ const grandChildClass = new ClassMirrorBuilder()
687
+ .withName('grandchild')
688
+ .addFiled(new FieldMirrorBuilder().withName('stringMember').withType('String').build())
689
+ .build();
690
+
691
+ TypesRepository.getInstance = jest.fn().mockReturnValue({
692
+ getFromAllByName: jest
693
+ .fn()
694
+ .mockReturnValueOnce({ type: mainClassMirror, isChild: false })
695
+ .mockReturnValueOnce({ type: childClass, isChild: false })
696
+ .mockReturnValueOnce({ type: grandChildClass, isChild: false }),
697
+ });
698
+
699
+ const result = new ReferenceBuilder().build('className');
700
+
701
+ expect(result.referenceComponents).toHaveLength(3);
702
+ expect(result.referenceComponents.some((ref) => ref.referencedClass === 'parent')).toBe(true);
703
+ expect(result.referenceComponents.some((ref) => ref.referencedClass === 'child')).toBe(true);
704
+ expect(result.referenceComponents.some((ref) => ref.referencedClass === 'grandchild')).toBe(true);
705
+ });
706
+ });
622
707
  });
@@ -1,11 +0,0 @@
1
- # SampleClassWithoutModifier
2
-
3
- `ISTEST`
4
- ## Methods
5
- ### `static thisIsAClassWithoutAModifier()`
6
-
7
- `ISTEST`
8
-
9
- This is a test method
10
-
11
- ---
@@ -1,10 +0,0 @@
1
- # GroupedClass
2
-
3
- Uses a block style apex doc
4
-
5
-
6
- **Group** Main
7
-
8
-
9
- **Test Class** [SampleClass](/Main/SampleClass.md)
10
-
@@ -1 +0,0 @@
1
- # AnotherInterface
@@ -1,7 +0,0 @@
1
- # Reference2
2
- ## Fields
3
-
4
- ### `stringMember` → `String`
5
-
6
-
7
- ---