Skip to content

Commit 965ca7a

Browse files
committed
feat(resolver): add support for parameterMacro option
This change is specific to OpenAPI 3.1.0 strategy. Refs #2748
1 parent bf6c109 commit 965ca7a

File tree

7 files changed

+518
-19
lines changed

7 files changed

+518
-19
lines changed

src/helpers/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ const OpenApi3_1SwaggerClientDereferenceStrategy = OpenApi3_1DereferenceStrategy
1212
props: {
1313
useCircularStructures: true,
1414
allowMetaPatches: false,
15+
parameterMacro: null,
1516
},
1617
init({
1718
useCircularStructures = this.useCircularStructures,
1819
allowMetaPatches = this.allowMetaPatches,
20+
parameterMacro = this.parameterMacro,
1921
} = {}) {
2022
this.name = 'openapi-3-1-swagger-client';
2123
this.useCircularStructures = useCircularStructures;
2224
this.allowMetaPatches = allowMetaPatches;
25+
this.parameterMacro = parameterMacro;
2326
},
2427
methods: {
2528
async dereference(file, options) {
@@ -41,6 +44,7 @@ const OpenApi3_1SwaggerClientDereferenceStrategy = OpenApi3_1DereferenceStrategy
4144
options,
4245
useCircularStructures: this.useCircularStructures,
4346
allowMetaPatches: this.allowMetaPatches,
47+
parameterMacro: this.parameterMacro,
4448
});
4549
const dereferencedElement = await visitAsync(refSet.rootRef.value, visitor, {
4650
keyMap,

src/helpers/apidom/reference/dereference/strategies/openapi-3-1-swagger-client/visitor.js

+67-18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
isPrimitiveElement,
55
isStringElement,
66
visit,
7+
toValue,
78
includesClasses,
89
} from '@swagger-api/apidom-core';
910
import {
@@ -40,17 +41,28 @@ import {
4041

4142
const visitAsync = visit[Symbol.for('nodejs.util.promisify.custom')];
4243

43-
const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.compose({
44-
props: {
45-
useCircularStructures: true,
46-
allowMetaPatches: false,
47-
},
48-
init({ useCircularStructures, allowMetaPatches }) {
44+
const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.init(
45+
function _OpenApi3_1SwaggerClientDereferenceVisitor({
46+
useCircularStructures = true,
47+
allowMetaPatches = false,
48+
parameterMacro = null,
49+
}) {
50+
const instance = this;
51+
let parameterMacroOperation = null;
52+
53+
// props
4954
this.useCircularStructures = useCircularStructures;
5055
this.allowMetaPatches = allowMetaPatches;
51-
},
52-
methods: {
53-
async ReferenceElement(referenceElement, key, parent, path, ancestors) {
56+
this.parameterMacro = parameterMacro;
57+
58+
// methods
59+
this.ReferenceElement = async function _ReferenceElement(
60+
referenceElement,
61+
key,
62+
parent,
63+
path,
64+
ancestors
65+
) {
5466
const [ancestorsLineage, directAncestors] = this.toAncestorLineage(ancestors);
5567

5668
// skip already identified cycled Path Item Objects
@@ -119,6 +131,7 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
119131
ancestors: ancestorsLineage,
120132
allowMetaPatches: this.allowMetaPatches,
121133
useCircularStructures: this.useCircularStructures,
134+
parameterMacro: this.parameterMacro,
122135
});
123136
fragment = await visitAsync(fragment, visitor, { keyMap, nodeTypeGetter: getNodeType });
124137

@@ -176,9 +189,15 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
176189

177190
// transclude the element for a fragment
178191
return fragment;
179-
},
180-
181-
async PathItemElement(pathItemElement, key, parent, path, ancestors) {
192+
};
193+
194+
this.PathItemElement = async function _PathItemElement(
195+
pathItemElement,
196+
key,
197+
parent,
198+
path,
199+
ancestors
200+
) {
182201
const [ancestorsLineage, directAncestors] = this.toAncestorLineage(ancestors);
183202

184203
// ignore PathItemElement without $ref field
@@ -242,6 +261,7 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
242261
ancestors: ancestorsLineage,
243262
allowMetaPatches: this.allowMetaPatches,
244263
useCircularStructures: this.useCircularStructures,
264+
parameterMacro: this.parameterMacro,
245265
});
246266
referencedElement = await visitAsync(referencedElement, visitor, {
247267
keyMap,
@@ -302,9 +322,15 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
302322

303323
// transclude referencing element with merged referenced element
304324
return mergedPathItemElement;
305-
},
306-
307-
async SchemaElement(referencingElement, key, parent, path, ancestors) {
325+
};
326+
327+
this.SchemaElement = async function _SchemaElement(
328+
referencingElement,
329+
key,
330+
parent,
331+
path,
332+
ancestors
333+
) {
308334
const [ancestorsLineage, directAncestors] = this.toAncestorLineage(ancestors);
309335

310336
// skip current referencing schema as $ref keyword was not defined
@@ -414,6 +440,7 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
414440
options: this.options,
415441
useCircularStructures: this.useCircularStructures,
416442
allowMetaPatches: this.allowMetaPatches,
443+
parameterMacro: this.parameterMacro,
417444
ancestors: ancestorsLineage,
418445
});
419446
referencedElement = await visitAsync(referencedElement, mergeVisitor, {
@@ -490,9 +517,31 @@ const OpenApi3_1SwaggerClientDereferenceVisitor = OpenApi3_1DereferenceVisitor.c
490517

491518
// transclude referencing element with merged referenced element
492519
return mergedSchemaElement;
493-
},
494-
},
495-
});
520+
};
521+
522+
this.OperationElement = {
523+
enter(operationElement) {
524+
parameterMacroOperation = operationElement;
525+
},
526+
leave() {
527+
parameterMacroOperation = null;
528+
},
529+
};
530+
531+
this.ParameterElement = {
532+
leave(parameterElement) {
533+
if (typeof instance.parameterMacro !== 'function') return;
534+
535+
const pojoOperation =
536+
parameterMacroOperation === null ? null : toValue(parameterMacroOperation);
537+
const pojoParameter = toValue(parameterElement);
538+
const defaultValue = instance.parameterMacro(pojoOperation, pojoParameter);
539+
540+
parameterElement.set('default', defaultValue);
541+
},
542+
};
543+
}
544+
);
496545

497546
export default OpenApi3_1SwaggerClientDereferenceVisitor;
498547
/* eslint-enable camelcase */

src/resolver/strategies/openapi-3-1.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const resolveOpenAPI31Strategy = async (options) => {
3434
allowMetaPatches = false,
3535
useCircularStructures = false,
3636
skipNormalization = false,
37+
parameterMacro = null,
3738
} = options;
3839
// determining BaseURI
3940
const defaultBaseURI = 'https://smartbear.com/';
@@ -90,7 +91,11 @@ const resolveOpenAPI31Strategy = async (options) => {
9091
},
9192
dereference: {
9293
strategies: [
93-
OpenApi3_1SwaggerClientDereferenceStrategy({ allowMetaPatches, useCircularStructures }),
94+
OpenApi3_1SwaggerClientDereferenceStrategy({
95+
allowMetaPatches,
96+
useCircularStructures,
97+
parameterMacro,
98+
}),
9499
],
95100
refSet,
96101
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"openapi": "3.1.0",
3+
"info": {
4+
"version": "1.0.0",
5+
"title": "Swagger Petstore",
6+
"license": {
7+
"name": "MIT"
8+
}
9+
},
10+
"components": {
11+
"parameters": {
12+
"limit": {
13+
"name": "limit",
14+
"in": "query",
15+
"description": "How many items to return at one time (max 100)",
16+
"required": false,
17+
"schema": {
18+
"type": "integer",
19+
"maximum": 100,
20+
"format": "int32"
21+
}
22+
}
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
{
2+
"openapi": "3.1.0",
3+
"info": {
4+
"version": "1.0.0",
5+
"title": "Swagger Petstore",
6+
"license": {
7+
"name": "MIT"
8+
}
9+
},
10+
"servers": [
11+
{
12+
"url": "http://petstore.swagger.io/v1"
13+
}
14+
],
15+
"paths": {
16+
"/pets": {
17+
"get": {
18+
"summary": "List all pets",
19+
"operationId": "listPets",
20+
"tags": [
21+
"pets"
22+
],
23+
"parameters": [
24+
{
25+
"name": "limit",
26+
"in": "query",
27+
"description": "How many items to return at one time (max 100)",
28+
"required": false,
29+
"schema": {
30+
"type": "integer",
31+
"maximum": 100,
32+
"format": "int32"
33+
}
34+
}
35+
],
36+
"responses": {
37+
"200": {
38+
"description": "A paged array of pets",
39+
"headers": {
40+
"x-next": {
41+
"description": "A link to the next page of responses",
42+
"schema": {
43+
"type": "string"
44+
}
45+
}
46+
},
47+
"content": {
48+
"application/json": {
49+
"schema": {
50+
"$ref": "#/components/schemas/Pets"
51+
}
52+
}
53+
}
54+
},
55+
"default": {
56+
"description": "unexpected error",
57+
"content": {
58+
"application/json": {
59+
"schema": {
60+
"$ref": "#/components/schemas/Error"
61+
}
62+
}
63+
}
64+
}
65+
}
66+
},
67+
"post": {
68+
"summary": "Create a pet",
69+
"operationId": "createPets",
70+
"tags": [
71+
"pets"
72+
],
73+
"responses": {
74+
"201": {
75+
"description": "Null response"
76+
},
77+
"default": {
78+
"description": "unexpected error",
79+
"content": {
80+
"application/json": {
81+
"schema": {
82+
"$ref": "#/components/schemas/Error"
83+
}
84+
}
85+
}
86+
}
87+
}
88+
}
89+
}
90+
},
91+
"components": {
92+
"schemas": {
93+
"Pet": {
94+
"type": "object",
95+
"required": [
96+
"id",
97+
"name"
98+
],
99+
"properties": {
100+
"id": {
101+
"type": "integer",
102+
"format": "int64"
103+
},
104+
"name": {
105+
"type": "string"
106+
},
107+
"tag": {
108+
"type": "string"
109+
}
110+
}
111+
},
112+
"Pets": {
113+
"type": "array",
114+
"maxItems": 100,
115+
"items": {
116+
"$ref": "#/components/schemas/Pet"
117+
}
118+
},
119+
"Error": {
120+
"type": "object",
121+
"required": [
122+
"code",
123+
"message"
124+
],
125+
"properties": {
126+
"code": {
127+
"type": "integer",
128+
"format": "int32"
129+
},
130+
"message": {
131+
"type": "string"
132+
}
133+
}
134+
}
135+
}
136+
}
137+
}

0 commit comments

Comments
 (0)