Skip to content

Commit 4634e8d

Browse files
committed
Merge branch 'develop' into fix496/validateWithServers
2 parents 1bdac02 + c4c5ea3 commit 4634e8d

File tree

16 files changed

+672
-48
lines changed

16 files changed

+672
-48
lines changed

.npmignore

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,16 @@ test/data/.temp
4343

4444
# Prevent unit test coverage reports from being added
4545
.coverage
46-
.nyc_output
46+
.nyc_output
47+
48+
# - Prevent config and test files from being added
49+
.git*
50+
.github/
51+
scripts/
52+
test/
53+
examples/
54+
.eslintrc
55+
.eslintignore
56+
.nycrc
57+
.editorconfig
58+
.jsdoc-config.json

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# OpenAPI-Postman Changelog
22

3+
#### v4.0.0 (July 12, 2022)
4+
* Added support for new multi-file API detectRootFiles() for OpenAPI 3 and Swagger 2 formats to support detection of root files among multiple files.
5+
* Added support for new multi-file API detectRelatedFiles() for OpenAPI 3 and Swagger 2 formats to support detection of related files for a provided root file amongst multiple files.
6+
* Added support for new multi-file API bundle() for OpenAPI 3 and Swagger 2 formats to support bundling of root files from provided multiple files.
7+
38
#### v3.2.0 (May 02, 2022)
49
* Fixed some of critical and high level severity vulnerabilities.
510
* Fixed issue [#10752](https://github.com/postmanlabs/postman-app-support/issues/10752) where deepObject style parameters were not generated correctly.

lib/bundle.js

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ let path = require('path'),
2222
{ DFS } = require('./dfs'),
2323
deref = require('./deref.js'),
2424
{ isSwagger, getBundleRulesDataByVersion } = require('./common/versionUtils'),
25-
CIRCULAR_REF_EXT_PROP = 'x-circularRef';
25+
CIRCULAR_OR_REF_EXT_PROP = 'x-orRef';
2626

2727

2828
/**
@@ -481,6 +481,34 @@ function findReferenceByMainKeyInTraceFromContext(documentContext, mainKeyInTrac
481481
return relatedRef;
482482
}
483483

484+
/**
485+
* Verifies if a node has same content as one of the parents so it is a circular ref
486+
* @param {function} traverseContext - The context of the traverse function
487+
* @param {object} contentFromTrace - The resolved content of the node to deref
488+
* @returns {boolean} whether is circular reference or not.
489+
*/
490+
function isCircularReference(traverseContext, contentFromTrace) {
491+
return traverseContext.parents.find((parent) => { return parent.node === contentFromTrace; }) !== undefined;
492+
}
493+
494+
/**
495+
* Modifies content of a node if it is circular reference.
496+
*
497+
* @param {function} traverseContext - The context of the traverse function
498+
* @param {object} documentContext The document context from root
499+
* @returns {undefined} nothing
500+
*/
501+
function handleCircularReference(traverseContext, documentContext) {
502+
let relatedRef = '';
503+
if (traverseContext.circular) {
504+
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, traverseContext.circular.key);
505+
traverseContext.update({ $ref: relatedRef });
506+
}
507+
if (traverseContext.keys && traverseContext.keys.includes(CIRCULAR_OR_REF_EXT_PROP)) {
508+
traverseContext.update({ $ref: traverseContext.node[CIRCULAR_OR_REF_EXT_PROP] });
509+
}
510+
}
511+
484512
/**
485513
* Generates the components object from the documentContext data
486514
* @param {object} documentContext The document context from root
@@ -492,8 +520,9 @@ function findReferenceByMainKeyInTraceFromContext(documentContext, mainKeyInTrac
492520
*/
493521
function generateComponentsObject (documentContext, rootContent, refTypeResolver, components, version) {
494522
let notInLine = Object.entries(documentContext.globalReferences).filter(([, value]) => {
495-
return value.keyInComponents.length !== 0;
496-
});
523+
return value.keyInComponents.length !== 0;
524+
}),
525+
circularRefsSet = new Set();
497526
const { COMPONENTS_KEYS } = getBundleRulesDataByVersion(version);
498527
notInLine.forEach(([key, value]) => {
499528
let [, partial] = key.split(localPointer);
@@ -541,6 +570,17 @@ function generateComponentsObject (documentContext, rootContent, refTypeResolver
541570
if (!contentFromTrace) {
542571
refData.nodeContent = { $ref: `${localPointer + local}` };
543572
}
573+
else if (isCircularReference(this, contentFromTrace)) {
574+
if (refData.inline) {
575+
refData.nodeContent = { [CIRCULAR_OR_REF_EXT_PROP]: tempRef };
576+
circularRefsSet.add(tempRef);
577+
}
578+
else {
579+
refData.node = { [CIRCULAR_OR_REF_EXT_PROP]: refData.reference };
580+
refData.nodeContent = contentFromTrace;
581+
circularRefsSet.add(refData.reference);
582+
}
583+
}
544584
else {
545585
refData.nodeContent = contentFromTrace;
546586
}
@@ -551,39 +591,30 @@ function generateComponentsObject (documentContext, rootContent, refTypeResolver
551591
refData.node = hasSiblings ?
552592
_.merge(referenceSiblings, refData.nodeContent) :
553593
refData.nodeContent;
554-
documentContext.globalReferences[property.$ref].reference =
594+
documentContext.globalReferences[tempRef].reference =
555595
resolveJsonPointerInlineNodes(this.parents, this.key);
556596
}
557-
this.update(refData.node);
558-
if (!refData.inline) {
559-
if (documentContext.globalReferences[tempRef].refHasContent) {
560-
setValueInComponents(
561-
refData.keyInComponents,
562-
components,
563-
refData.nodeContent,
564-
COMPONENTS_KEYS
565-
);
566-
}
597+
else if (refData.refHasContent) {
598+
setValueInComponents(
599+
refData.keyInComponents,
600+
components,
601+
refData.nodeContent,
602+
COMPONENTS_KEYS
603+
);
567604
}
605+
this.update(refData.node);
568606
}
569607
}
570608
});
571609
});
572610
return {
573611
resRoot: traverseUtility(rootContent).map(function () {
574-
let relatedRef = '';
575-
if (this.circular) {
576-
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, this.circular.key);
577-
this.update({ $ref: relatedRef, [CIRCULAR_REF_EXT_PROP]: true });
578-
}
612+
handleCircularReference(this, documentContext);
579613
}),
580614
newComponents: traverseUtility(components).map(function () {
581-
let relatedRef = '';
582-
if (this.circular) {
583-
relatedRef = findReferenceByMainKeyInTraceFromContext(documentContext, this.circular.key);
584-
this.update({ $ref: relatedRef, [CIRCULAR_REF_EXT_PROP]: true });
585-
}
586-
})
615+
handleCircularReference(this, documentContext);
616+
}),
617+
circularRefs: [...circularRefsSet]
587618
};
588619
}
589620

@@ -618,7 +649,7 @@ function generateComponentsWrapper(parsedOasObject, version, nodesContent = {})
618649
}
619650

620651
/**
621-
* Generates a map of generated refernce to the original reference
652+
* Generates a map of generated reference to the original reference
622653
*
623654
* @param {object} globalReferences - Global references present at each root file context
624655
* @returns {object} reference map
@@ -712,7 +743,8 @@ module.exports = {
712743
fileContent: finalElements.resRoot,
713744
components: finalElements.newComponents,
714745
fileName: specRoot.fileName,
715-
referenceMap: getReferenceMap(rootContextData.globalReferences)
746+
referenceMap: getReferenceMap(rootContextData.globalReferences),
747+
circularRefs: finalElements.circularRefs
716748
};
717749
},
718750
getReferences,

lib/common/schemaUtilsCommon.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function removeWordFromLastPosition(schemaPath, word) {
6363
* "<integer>"
6464
*
6565
* @param {string} value - Value to check for
66-
* @param {string} type - The type in the schemna
66+
* @param {string} type - The type in the schema
6767
* @returns {Boolean} the value is the representation of its type
6868
*/
6969
function compareType(value, type) {
@@ -75,7 +75,7 @@ function compareType(value, type) {
7575
* "<integer>"
7676
* Works in array types
7777
* @param {string} value - Value to check for
78-
* @param {*} types - The types in the schemna
78+
* @param {*} types - The types in the schema
7979
* @returns {Boolean} the value is the representation of its type
8080
*/
8181
function isTypeValueArrayCheck(value, types) {
@@ -89,7 +89,7 @@ function isTypeValueArrayCheck(value, types) {
8989
* "<integer>"
9090
* Works in array types
9191
* @param {string} value - Value to check for
92-
* @param {*} types - The types in the schemna
92+
* @param {*} types - The types in the schema
9393
* @returns {Boolean} the value is the representation of its type
9494
*/
9595
function checkValueOnlyTypes(value, types) {
@@ -118,7 +118,7 @@ function getDefaultFromTypeAndFormat(type, format) {
118118
* @returns {Boolean} the value is the representation of its type
119119
*/
120120
function checkValueTypesAndFormat(value, types, format) {
121-
let typesNotInMapp = [],
121+
let typesNotInMap = [],
122122
typesArray = Array.isArray(types) ? types : [types],
123123
found = typesArray.find((type) => {
124124
let defaultValue;
@@ -132,7 +132,7 @@ function checkValueTypesAndFormat(value, types, format) {
132132
}
133133
}
134134
else {
135-
typesNotInMapp.push(type);
135+
typesNotInMap.push(type);
136136
}
137137
return defaultValue === value;
138138
});
@@ -141,7 +141,7 @@ function checkValueTypesAndFormat(value, types, format) {
141141
return true;
142142
}
143143

144-
found = typesNotInMapp.find((type) => {
144+
found = typesNotInMap.find((type) => {
145145
let defaultValue;
146146
defaultValue = '<' + type + (format ? ('-' + format) : '') + '>';
147147
return defaultValue === value;
@@ -185,7 +185,7 @@ function isTypeValue(value, schema) {
185185
}
186186

187187
/**
188-
* Checks if value is correcta according to schema
188+
* Checks if value is correct according to schema
189189
* If the value should be numeric, it tries to convert and then validate
190190
* also validates if the value is a correct representation in the form of
191191
* <long> or <integer> etc for integers format 32 or format 64
@@ -332,7 +332,7 @@ module.exports = {
332332
isTypeValue,
333333

334334
/**
335-
* Checks if value is correcta according to schema
335+
* Checks if value is correct according to schema
336336
* If the value should be numeric, it tries to convert and then validate
337337
* also validates if the value is a correct representation in the form of
338338
* <long> or <integer> etc for integers format 32 or format 64

lib/schemaUtils.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,10 @@ module.exports = {
18271827
bodyData = this.convertToPmBodyData(contentObj[FORM_DATA], requestType, FORM_DATA,
18281828
PARAMETER_SOURCE.REQUEST, options.indentCharacter, components, options, schemaCache);
18291829
encoding = contentObj[FORM_DATA].encoding ? contentObj[FORM_DATA].encoding : {};
1830+
1831+
if (contentObj[FORM_DATA].hasOwnProperty('schema') && contentObj[FORM_DATA].schema.hasOwnProperty('$ref')) {
1832+
contentObj[FORM_DATA].schema = this.getRefObject(contentObj[FORM_DATA].schema.$ref, components, options);
1833+
}
18301834
// create the form parameters and add it to the request body object
18311835
_.forOwn(bodyData, (value, key) => {
18321836

@@ -2454,9 +2458,6 @@ module.exports = {
24542458
pmBody = this.convertToPmBody(reqBody, REQUEST_TYPE.ROOT, components, options, schemaCache);
24552459
item.request.body = pmBody.body;
24562460

2457-
// Following is added to make sure body pruning for request methods like GET, HEAD etc is disabled'.
2458-
item.protocolProfileBehavior = { disableBodyPruning: true };
2459-
24602461
if (!options.keepImplicitHeaders || (!_.find(reqParams.header, (h) => {
24612462
return _.toLower(_.get(h, 'name')) === 'content-type';
24622463
}))) {
@@ -2568,6 +2569,13 @@ module.exports = {
25682569
if (!_.isEmpty(acceptHeader) && !item.request.headers.has('accept')) {
25692570
item.request.addHeader(acceptHeader);
25702571
}
2572+
2573+
/**
2574+
* Following is added to make sure body pruning for request methods like GET, HEAD etc is disabled'.
2575+
* https://github.com/postmanlabs/postman-runtime/blob/develop/docs/protocol-profile-behavior.md
2576+
*/
2577+
item.protocolProfileBehavior = { disableBodyPruning: true };
2578+
25712579
return item;
25722580
},
25732581

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openapi-to-postmanv2",
3-
"version": "3.2.0",
3+
"version": "4.0.0",
44
"description": "Convert a given OpenAPI specification to Postman Collection v2.0",
55
"homepage": "https://github.com/postmanlabs/openapi-to-postman",
66
"bugs": "https://github.com/postmanlabs/openapi-to-postman/issues",

test/data/toBundleExamples/circular_reference/expected.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"schema": {
2929
"type": "array",
3030
"items": {
31-
"$ref": "#/components/schemas/_schemas_schemas.yaml-components_schemas_ErrorDetail"
31+
"$ref": "#/components/schemas/_schemas_schemas.yaml-_components_schemas_ErrorDetail"
3232
}
3333
}
3434
}
@@ -40,7 +40,7 @@
4040
},
4141
"components": {
4242
"schemas": {
43-
"_schemas_schemas.yaml-components_schemas_ErrorDetail": {
43+
"_schemas_schemas.yaml-_components_schemas_ErrorDetail": {
4444
"type": "object",
4545
"description": "The error detail.",
4646
"properties": {
@@ -63,8 +63,7 @@
6363
"readOnly": true,
6464
"type": "array",
6565
"items": {
66-
"$ref": "#/components/schemas/_schemas_schemas.yaml-components_schemas_ErrorDetail",
67-
"x-circularRef": true
66+
"$ref": "#/components/schemas/_schemas_schemas.yaml-_components_schemas_ErrorDetail"
6867
},
6968
"description": "The error details."
7069
}

test/data/toBundleExamples/circular_reference/root.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ paths:
2525
schema:
2626
type: array
2727
items:
28-
$ref: "./schemas/schemas.yaml#components/schemas/ErrorDetail"
28+
$ref: "./schemas/schemas.yaml#/components/schemas/ErrorDetail"

0 commit comments

Comments
 (0)