@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.
- package/README.md +111 -66
- package/docs/Main/nspc.GroupedClass.md +10 -0
- package/docs/Main/{SampleClass.md → nspc.SampleClass.md} +21 -18
- package/docs/Misc-Group/nspc.AnotherInterface.md +1 -0
- package/docs/Misc-Group/{ChildClass.md → nspc.ChildClass.md} +4 -4
- package/docs/Misc-Group/{GrandparentClass.md → nspc.GrandparentClass.md} +1 -1
- package/docs/Misc-Group/{InterfaceWithInheritance.md → nspc.InterfaceWithInheritance.md} +3 -3
- package/docs/Misc-Group/nspc.MemberGrouping.md +13 -0
- package/docs/Misc-Group/{ParentClass.md → nspc.ParentClass.md} +2 -2
- package/docs/Misc-Group/{Reference1.md → nspc.Reference1.md} +1 -1
- package/docs/Misc-Group/nspc.Reference2.md +12 -0
- package/docs/Misc-Group/{Reference3.md → nspc.Reference3.md} +1 -1
- package/docs/Misc-Group/{Reference4.md → nspc.Reference4.md} +1 -1
- package/docs/Misc-Group/{Reference5.md → nspc.Reference5.md} +1 -1
- package/docs/Misc-Group/{Reference6.md → nspc.Reference6.md} +1 -1
- package/docs/Misc-Group/{SampleClassWithoutModifier.md → nspc.SampleClassWithoutModifier.md} +1 -1
- package/docs/Misc-Group/{SampleRestResource.md → nspc.SampleRestResource.md} +1 -4
- package/docs/Misc-Group/{SampleRestResourceWithInnerClass.md → nspc.SampleRestResourceWithInnerClass.md} +1 -1
- package/docs/Misc-Group/nspc.SampleRestResourceWithoutApexDocs.md +14 -0
- package/docs/README.md +28 -19
- package/docs/Sample-Interfaces/{SampleInterface.md → nspc.SampleInterface.md} +1 -1
- package/docs/index.html +22 -22
- package/docs/{openapi.json → restapi.json} +77 -13
- package/examples/force-app/main/default/classes/MemberGrouping.cls +16 -0
- package/examples/force-app/main/default/classes/SampleClass.cls +3 -0
- package/examples/force-app/main/default/restapi/SampleRestResource.cls +0 -4
- package/examples/force-app/main/default/restapi/SampleRestResourceWithoutApexDocs.cls +15 -0
- package/examples/force-app/main/default/restapi/references/Reference2.cls +6 -0
- package/lib/cli/generate.js +12 -0
- package/lib/cli/generate.js.map +1 -1
- package/lib/model/markdown-generation-util/field-declaration-util.js +6 -1
- package/lib/model/markdown-generation-util/field-declaration-util.js.map +1 -1
- package/lib/model/markdown-type-file.d.ts +4 -3
- package/lib/model/markdown-type-file.js +21 -7
- package/lib/model/markdown-type-file.js.map +1 -1
- package/lib/model/openapi/open-api.d.ts +1 -1
- package/lib/model/openapi/open-api.js.map +1 -1
- package/lib/model/openapi/openapi-type-file.js +3 -2
- package/lib/model/openapi/openapi-type-file.js.map +1 -1
- package/lib/settings.d.ts +5 -0
- package/lib/settings.js +12 -0
- package/lib/settings.js.map +1 -1
- package/lib/test-helpers/DocCommentAnnotationBuilder.d.ts +2 -0
- package/lib/test-helpers/DocCommentAnnotationBuilder.js +6 -1
- package/lib/test-helpers/DocCommentAnnotationBuilder.js.map +1 -1
- package/lib/test-helpers/FieldMirrorBuilder.d.ts +3 -1
- package/lib/test-helpers/FieldMirrorBuilder.js +6 -0
- package/lib/test-helpers/FieldMirrorBuilder.js.map +1 -1
- package/lib/test-helpers/SettingsBuilder.js +1 -0
- package/lib/test-helpers/SettingsBuilder.js.map +1 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.js +2 -1
- package/lib/transpiler/markdown/class-file-generatorHelper.js.map +1 -1
- package/lib/transpiler/openapi/open-api-docs-processor.d.ts +1 -0
- package/lib/transpiler/openapi/open-api-docs-processor.js +4 -2
- package/lib/transpiler/openapi/open-api-docs-processor.js.map +1 -1
- package/lib/transpiler/openapi/parsers/MethodParser.d.ts +3 -0
- package/lib/transpiler/openapi/parsers/MethodParser.js +80 -19
- package/lib/transpiler/openapi/parsers/MethodParser.js.map +1 -1
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.d.ts +10 -2
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js +35 -5
- package/lib/transpiler/openapi/parsers/ReferenceBuilder.js.map +1 -1
- package/package.json +5 -5
- package/src/cli/generate.ts +13 -0
- package/src/model/markdown-generation-util/field-declaration-util.ts +8 -3
- package/src/model/markdown-type-file.ts +25 -9
- package/src/model/openapi/open-api.ts +1 -1
- package/src/model/openapi/openapi-type-file.ts +3 -2
- package/src/service/__tests__/apex-file-reader.spec.ts +1 -0
- package/src/settings.ts +17 -0
- package/src/test-helpers/DocCommentAnnotationBuilder.ts +7 -1
- package/src/test-helpers/FieldMirrorBuilder.ts +8 -1
- package/src/test-helpers/SettingsBuilder.ts +1 -0
- package/src/transpiler/markdown/class-file-generatorHelper.ts +2 -1
- package/src/transpiler/openapi/open-api-docs-processor.ts +4 -2
- package/src/transpiler/openapi/parsers/MethodParser.ts +134 -30
- package/src/transpiler/openapi/parsers/ReferenceBuilder.ts +42 -6
- package/src/transpiler/openapi/parsers/__tests__/ReferenceBuilder.spec.ts +85 -0
- package/docs/API/SampleClassWithoutModifier.md +0 -11
- package/docs/Main/GroupedClass.md +0 -10
- package/docs/Misc-Group/AnotherInterface.md +0 -1
- package/docs/Misc-Group/Reference2.md +0 -7
|
@@ -11,7 +11,8 @@ export default class ClassFileGeneratorHelper {
|
|
|
11
11
|
|
|
12
12
|
public static getFileLink(classModel: Type) {
|
|
13
13
|
const directoryRoot = this.getDirectoryRoot(classModel);
|
|
14
|
-
|
|
14
|
+
const fullClassName = `${Settings.getInstance().getNamespacePrefix()}${classModel.name}`;
|
|
15
|
+
return `[${fullClassName}](${directoryRoot}${fullClassName}.md)`;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
public static getFileLinkByTypeName(typeName: string) {
|
|
@@ -18,7 +18,7 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
|
|
|
18
18
|
if (!title) {
|
|
19
19
|
throw Error('No OpenApi title was provided.');
|
|
20
20
|
}
|
|
21
|
-
this.openApiModel = new OpenApi(title, '1.0.0');
|
|
21
|
+
this.openApiModel = new OpenApi(title, '1.0.0', Settings.getInstance().getNamespace());
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
fileBuilder(): FileContainer {
|
|
@@ -57,9 +57,11 @@ export class OpenApiDocsProcessor extends ProcessorTypeTranspiler {
|
|
|
57
57
|
|
|
58
58
|
// DELETE
|
|
59
59
|
parser.parseMethod(typeAsClass, endpointPath, 'delete');
|
|
60
|
+
}
|
|
60
61
|
|
|
62
|
+
onAfterProcess: ((types: Type[]) => void) | undefined = () => {
|
|
61
63
|
this._fileContainer.pushFile(new OpenapiTypeFile(this.openApiModel));
|
|
62
|
-
}
|
|
64
|
+
};
|
|
63
65
|
|
|
64
66
|
private getEndpointPath(type: Type): string | null {
|
|
65
67
|
const restResourceAnnotation = type.annotations.find((element) => element.name.toLowerCase() === 'restresource');
|
|
@@ -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
|
|
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(
|
|
43
|
-
|
|
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
|
-
|
|
46
|
-
|
|
53
|
+
|
|
54
|
+
this.parseHttpAnnotation<ApexDocParameterObject>(
|
|
55
|
+
httpMethod,
|
|
56
|
+
httpUrlEndpoint,
|
|
57
|
+
httpMethodKey,
|
|
58
|
+
'http-parameter',
|
|
59
|
+
this.addParametersToOpenApi.bind(this),
|
|
47
60
|
);
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
97
|
+
this.addToOpenApiStrategy<T>(inYaml, urlValue, httpMethodKey, addToOpenApi);
|
|
76
98
|
}
|
|
77
99
|
}
|
|
78
100
|
|
|
79
|
-
private
|
|
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
|
|
108
|
+
const inJson = yaml.load(inYaml) as T;
|
|
82
109
|
const requestBodyResponse = new RequestBodyBuilder().build(inJson);
|
|
83
110
|
|
|
84
|
-
|
|
111
|
+
addToOpenApi(inJson, urlValue, httpMethodKey);
|
|
85
112
|
|
|
86
113
|
this.addReference(requestBodyResponse);
|
|
87
114
|
}
|
|
88
115
|
|
|
89
|
-
private
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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(
|
|
104
|
-
|
|
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![
|
|
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
|
-
|
|
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
|
|
10
|
+
import { ClassMirror, DocCommentAnnotation, FieldMirror, PropertyMirror } from '@cparra/apex-reflection';
|
|
10
11
|
import { ListObjectType, ReferencedType } from '@cparra/apex-reflection/index';
|
|
12
|
+
import { ApexDocSchemaObject } from '../../../model/openapi/apex-doc-types';
|
|
11
13
|
|
|
12
14
|
type TypeBundleWithIsCollection = TypeBundle & { isCollection: boolean };
|
|
13
15
|
|
|
@@ -64,12 +66,20 @@ export class ReferenceBuilder {
|
|
|
64
66
|
const properties: PropertiesObject = {};
|
|
65
67
|
let referencedComponents: ReferenceComponent[] = [];
|
|
66
68
|
propertiesAndFields.forEach((current) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
// Check for "@http-schema" annotations within properties themselves. If these are specified they
|
|
70
|
+
// take precedence over the property type itself.
|
|
71
|
+
const manuallyDefinedHttpSchema = current.docComment?.annotations.find(
|
|
72
|
+
(annotation) => annotation.name.toLowerCase() === 'http-schema',
|
|
73
|
+
);
|
|
74
|
+
if (manuallyDefinedHttpSchema) {
|
|
75
|
+
this.handleOverriddenSchema(manuallyDefinedHttpSchema, properties, current, referencedComponents);
|
|
76
|
+
} else {
|
|
77
|
+
const pair = this.getReferenceType(current.typeReference);
|
|
78
|
+
properties[current.name] = pair.schema;
|
|
79
|
+
pair.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
80
|
+
}
|
|
69
81
|
properties[current.name].description = current.docComment?.description;
|
|
70
|
-
pair.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
71
82
|
});
|
|
72
|
-
|
|
73
83
|
const mainReferenceComponents = this.buildMainReferenceComponent(typeBundle, properties);
|
|
74
84
|
|
|
75
85
|
// Make sure to add the "main" reference first
|
|
@@ -83,6 +93,28 @@ export class ReferenceBuilder {
|
|
|
83
93
|
};
|
|
84
94
|
}
|
|
85
95
|
|
|
96
|
+
private handleOverriddenSchema(
|
|
97
|
+
manuallyDefinedHttpSchema: DocCommentAnnotation,
|
|
98
|
+
properties: PropertiesObject,
|
|
99
|
+
current: FieldMirror | PropertyMirror,
|
|
100
|
+
referencedComponents: ReferenceComponent[],
|
|
101
|
+
) {
|
|
102
|
+
// This can be of type ApexDocSchemaObject
|
|
103
|
+
const inYaml = manuallyDefinedHttpSchema?.bodyLines.reduce((prev, current, _) => prev + '\n' + current);
|
|
104
|
+
const asJson = yaml.load(inYaml) as ApexDocSchemaObject;
|
|
105
|
+
const isReference = this.isReferenceString(asJson);
|
|
106
|
+
|
|
107
|
+
if (isReference) {
|
|
108
|
+
const reference = this.build(asJson);
|
|
109
|
+
properties[current.name] = reference.entrypointReferenceObject;
|
|
110
|
+
reference.referenceComponents.forEach((current) => referencedComponents.push(current));
|
|
111
|
+
} else {
|
|
112
|
+
// If we are dealing with a manually defined schema object, we can add it directly to the "properties" map,
|
|
113
|
+
// because we don't need to add a reference component.
|
|
114
|
+
properties[current.name] = asJson;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
86
118
|
private getReferenceName(typeBundle: TypeBundleWithIsCollection): string {
|
|
87
119
|
let referenceName = typeBundle.type.name;
|
|
88
120
|
if (typeBundle.isChild) {
|
|
@@ -127,7 +159,7 @@ export class ReferenceBuilder {
|
|
|
127
159
|
];
|
|
128
160
|
}
|
|
129
161
|
|
|
130
|
-
|
|
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 +0,0 @@
|
|
|
1
|
-
# AnotherInterface
|