Skip to content

Commit a658668

Browse files
committed
feat: add extensions support to additional objects
Refs #16
1 parent 0dc34ab commit a658668

File tree

5 files changed

+60
-18
lines changed

5 files changed

+60
-18
lines changed

apidom/packages/apidom-parser-adapter-openapi3/src/parser/parsers/info.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
const { partition } = require('ramda');
44
const { addSourceMap } = require('../source-map');
55
const { isOpenApiExtension } = require('../predicates');
6-
const parseOpenApiExtension = require('./open-api-extension');
6+
const { parseOpenApiExtension, parseOpenApiExtensions } = require('./open-api-extension');
77

88
// parseContact :: (Options, JsonNode) -> Element
99
const parseContact = ({ namespace, sourceMap }, node) => {
1010
const contactKeyElement = new namespace.elements.String('contact');
11-
const contactElement = new namespace.elements.Object();
11+
let contactElement = new namespace.elements.Object();
1212
const { MemberElement } = namespace.elements.Element.prototype;
1313
const [openApiExtensions, properties] = partition(isOpenApiExtension({}), node.value.properties);
1414

@@ -22,9 +22,9 @@ const parseContact = ({ namespace, sourceMap }, node) => {
2222
))
2323
});
2424

25-
openApiExtensions.forEach(propertyNode => {
26-
contactElement.content.push(parseOpenApiExtension({ namespace, sourceMap }, propertyNode));
27-
});
25+
contactElement = contactElement.concat(
26+
parseOpenApiExtensions({ namespace, sourceMap }, openApiExtensions)
27+
);
2828

2929
contactElement.classes.push('contact');
3030

@@ -37,7 +37,7 @@ const parseContact = ({ namespace, sourceMap }, node) => {
3737
// parseLicense :: (Options, JsonNode) -> Element
3838
const parseLicense = ({ namespace, sourceMap }, node) => {
3939
const licenseKeyElement = new namespace.elements.String('license');
40-
const licenseElement = new namespace.elements.Object();
40+
let licenseElement = new namespace.elements.Object();
4141
const { MemberElement } = namespace.elements.Element.prototype;
4242
const [openApiExtensions, properties] = partition(isOpenApiExtension({}), node.value.properties);
4343

@@ -51,9 +51,9 @@ const parseLicense = ({ namespace, sourceMap }, node) => {
5151
))
5252
});
5353

54-
openApiExtensions.forEach(propertyNode => {
55-
licenseElement.content.push(parseOpenApiExtension({ namespace, sourceMap }, propertyNode));
56-
});
54+
licenseElement = licenseElement.concat(
55+
parseOpenApiExtensions({ namespace, sourceMap }, openApiExtensions)
56+
);
5757

5858
licenseElement.classes.push('license');
5959

apidom/packages/apidom-parser-adapter-openapi3/src/parser/parsers/open-api-extension.js

+14-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,17 @@ const parseOpenApiExtension = ({ namespace, sourceMap }, node) => {
2626
return memberElement;
2727
};
2828

29-
module.exports = parseOpenApiExtension;
29+
// parseOpenApiExtensions :: (Options, Array.<PropertyNode>) -> Element
30+
const parseOpenApiExtensions = ({ namespace, sourceMap, accumulator }, nodeList) => {
31+
return nodeList
32+
.filter(isOpenApiExtension({}))
33+
.reduce((acc, node) => {
34+
acc.push(parseOpenApiExtension({ namespace, sourceMap }, node));
35+
return acc;
36+
}, new namespace.elements.Array());
37+
};
38+
39+
module.exports = {
40+
parseOpenApiExtension,
41+
parseOpenApiExtensions,
42+
};

apidom/packages/apidom-parser-adapter-openapi3/src/parser/parsers/open-api3.js

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
const parseOpenapi = require('./openapi');
44
const parseInfo = require('./info');
55
const parseComponents = require('./components');
6+
const { parseOpenApiExtension } = require('./open-api-extension');
7+
const { isOpenApiExtension } = require('../predicates');
68

79
// parseOpenApi3 :: (Options, JsonNode) -> Element
810
const parseOpenApi3 = ({ namespace, sourceMap }, node) => {
@@ -16,6 +18,8 @@ const parseOpenApi3 = ({ namespace, sourceMap }, node) => {
1618
openApi3Element.content.push(parseInfo(state, propertyNode));
1719
} else if (propertyNode.key.value === 'components') {
1820
openApi3Element.content.push(parseComponents(state, propertyNode));
21+
} else if (isOpenApiExtension({}, propertyNode)) {
22+
openApi3Element.content.push(parseOpenApiExtension(state, propertyNode));
1923
}
2024
});
2125

apidom/packages/apidom-parser-adapter-openapi3/src/parser/visitors/generics.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { last } = require('ramda');
44
const { isNotNull } = require('ramda-adjunct');
55
const { addSourceMap } = require('../source-map');
66
const { visit, BREAK } = require('../visitor');
7+
const { isOpenApiExtension } = require('../predicates');
78

89
const ArrayVisitor = () => {
910
const stack = [];
@@ -117,16 +118,30 @@ const ObjectVisitor = () => {
117118
} else if (propertyNode.key.value === '$ref') { // $ref property key special handling
118119
valueElement = new this.namespace.elements.Ref(propertyNode.value.value);
119120
valueElement.path = propertyNode.value.value;
120-
} else {
121+
} else if (!isOpenApiExtension({}, propertyNode)) {
121122
valueElement = this.namespace.toElement(propertyNode.value.value);
122123
}
123124

124-
objElement.content.push(
125-
new MemberElement(
126-
this.sourceMap ? addSourceMap(propertyNode.key, keyElement) : keyElement,
127-
this.sourceMap ? addSourceMap(propertyNode.value, valueElement): valueElement,
128-
)
129-
);
125+
/**
126+
* @todo([email protected]): we have a circular dependency here which needs to be eliminated in future.
127+
*/
128+
if (isOpenApiExtension({}, propertyNode)) {
129+
const { parseOpenApiExtension } = require('../parsers/open-api-extension');
130+
131+
objElement.content.push(
132+
parseOpenApiExtension(
133+
{ namespace: this.namespace, sourceMap: this.sourceMap },
134+
propertyNode
135+
)
136+
);
137+
} else {
138+
objElement.content.push(
139+
new MemberElement(
140+
this.sourceMap ? addSourceMap(propertyNode.key, keyElement) : keyElement,
141+
this.sourceMap ? addSourceMap(propertyNode.value, valueElement): valueElement,
142+
)
143+
);
144+
}
130145

131146
return false;
132147
},

apidom/packages/apidom-parser-adapter-openapi3/test/fixtures/sample-api.json

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"openapi": "3.0.0",
3+
"x-top-level": "value",
34
"info": {
45
"title": "Sample API",
56
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
@@ -20,6 +21,14 @@
2021
},
2122
"components": {
2223
"schemas": {
24+
"x-model": {
25+
"type": "object",
26+
"properties": {
27+
"id": {
28+
"type:": "integer"
29+
}
30+
}
31+
},
2332
"User": {
2433
"type": "object",
2534
"properties": {
@@ -38,7 +47,8 @@
3847
"type": "object",
3948
"properties": {
4049
"email": {
41-
"type": "string"
50+
"type": "string",
51+
"x-nullable": true
4252
}
4353
}
4454
}

0 commit comments

Comments
 (0)