Skip to content

Commit d3967c3

Browse files
authored
Merge pull request #733 from postmanlabs/release/v4.14.0
Release version v4.14.0
2 parents 856428a + a10e847 commit d3967c3

21 files changed

+827
-245
lines changed

CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22

33
## [Unreleased]
44

5+
## [v4.14.0] - 2023-06-07
6+
7+
### Added
8+
9+
- Added support for consumption of schema level examples while generating data from XML schemas.
10+
11+
### Fixed
12+
13+
- Fixed the default value of auth in the generated request when it is not resolved.
14+
- Fixed issue where collection name was empty in cases where definition title was defined as empty string.
15+
516
## [v4.13.0] - 2023-05-24
617

718
### Added
@@ -562,7 +573,9 @@ Newer releases follow the [Keep a Changelog](https://keepachangelog.com/en/1.0.0
562573

563574
- Base release
564575

565-
[Unreleased]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.13.0...HEAD
576+
[Unreleased]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.14.0...HEAD
577+
578+
[v4.14.0]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.13.0...v4.14.0
566579

567580
[v4.13.0]: https://github.com/postmanlabs/openapi-to-postman/compare/v4.12.0...v4.13.0
568581

OPTIONS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ allowUrlPathVarMatching|boolean|-|false|Whether to allow matching path variables
2121
enableOptionalParameters|boolean|-|true|Optional parameters aren't selected in the collection. Once enabled they will be selected in the collection and request as well.|CONVERSION|v2, v1
2222
keepImplicitHeaders|boolean|-|false|Whether to keep implicit headers from the OpenAPI specification, which are removed by default.|CONVERSION|v2, v1
2323
includeDeprecated|boolean|-|true|Select whether to include deprecated operations, parameters, and properties in generated collection or not|CONVERSION, VALIDATION|v2, v1
24+
alwaysInheritAuthentication|boolean|-|false|Whether authentication details should be included on every request, or always inherited from the collection.|CONVERSION|v2, v1

lib/options.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,18 @@ module.exports = {
374374
usage: ['CONVERSION', 'VALIDATION'],
375375
supportedIn: [VERSION20, VERSION30, VERSION31],
376376
supportedModuleVersion: [MODULE_VERSION.V2, MODULE_VERSION.V1]
377+
},
378+
{
379+
name: 'Always inherit authentication',
380+
id: 'alwaysInheritAuthentication',
381+
type: 'boolean',
382+
default: false,
383+
description: 'Whether authentication details should be included on every request, or always inherited from ' +
384+
'the collection.',
385+
external: true,
386+
usage: ['CONVERSION'],
387+
supportedIn: [VERSION20, VERSION30, VERSION31],
388+
supportedModuleVersion: [MODULE_VERSION.V2, MODULE_VERSION.V1]
377389
}
378390
];
379391

lib/schemaUtils.js

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const { formatDataPath, checkIsCorrectType, isKnownType } = require('./common/sc
1313
deref = require('./deref.js'),
1414
_ = require('lodash'),
1515
xmlFaker = require('./xmlSchemaFaker.js'),
16-
js2xml = require('./common/js2xml.js'),
1716
openApiErr = require('./error.js'),
1817
ajvValidationError = require('./ajValidation/ajvValidationError'),
1918
utils = require('./utils.js'),
@@ -242,7 +241,7 @@ function safeSchemaFaker (oldSchema, resolveTo, resolveFor, parameterSourceOptio
242241

243242
try {
244243
if (schemaFormat === SCHEMA_FORMATS.XML) {
245-
fakedSchema = xmlFaker(null, resolvedSchema, indentCharacter);
244+
fakedSchema = xmlFaker(null, resolvedSchema, indentCharacter, resolveTo);
246245
schemaFakerCache[key] = fakedSchema;
247246
return fakedSchema;
248247
}
@@ -1607,15 +1606,27 @@ module.exports = {
16071606

16081607
// Convert example into XML if present as JSON data
16091608
if (contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML) {
1610-
bodyData = js2xml(bodyData, indentCharacter);
1609+
let bodySchemaWithExample = bodyObj.schema;
1610+
1611+
// Assign example at schema level to be faked by xmlSchemaFaker
1612+
if (typeof bodyObj.schema === 'object') {
1613+
bodySchemaWithExample = Object.assign({}, bodyObj.schema, { example: bodyData });
1614+
}
1615+
bodyData = xmlFaker(null, bodySchemaWithExample, indentCharacter, resolveTo);
16111616
}
16121617
}
16131618
else if (!_.isEmpty(bodyObj.examples) && (resolveTo === 'example' || !bodyObj.schema)) {
16141619
// take one of the examples as the body and not all
16151620
bodyData = this.getExampleData(bodyObj.examples, components, options);
16161621

16171622
if (contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML) {
1618-
bodyData = js2xml(bodyData, indentCharacter);
1623+
let bodySchemaWithExample = bodyObj.schema;
1624+
1625+
// Assign example at schema level to be faked by xmlSchemaFaker
1626+
if (typeof bodyObj.schema === 'object') {
1627+
bodySchemaWithExample = Object.assign({}, bodyObj.schema, { example: bodyData });
1628+
}
1629+
bodyData = xmlFaker(null, bodySchemaWithExample, indentCharacter, resolveTo);
16191630
}
16201631
}
16211632
else if (bodyObj.schema) {
@@ -1652,17 +1663,8 @@ module.exports = {
16521663
return '<Error: Spec size too large, skipping faking of schemas>';
16531664
}
16541665

1655-
if (
1656-
resolveTo === 'example' &&
1657-
_.get(bodyObj.schema, 'example') !== undefined &&
1658-
(contentType === TEXT_XML || contentType === APP_XML || headerFamily === HEADER_TYPE.XML)
1659-
) {
1660-
bodyData = js2xml(bodyObj.schema.example, indentCharacter);
1661-
}
1662-
else {
1663-
bodyData = safeSchemaFaker(bodyObj.schema || {}, resolveTo, PROCESSING_TYPE.CONVERSION, parameterSourceOption,
1664-
components, schemaFormat, schemaCache, options);
1665-
}
1666+
bodyData = safeSchemaFaker(bodyObj.schema || {}, resolveTo, PROCESSING_TYPE.CONVERSION, parameterSourceOption,
1667+
components, schemaFormat, schemaCache, options);
16661668
}
16671669
else {
16681670
// do not fake if the option is false
@@ -2647,7 +2649,9 @@ module.exports = {
26472649
}
26482650

26492651
// handling authentication here (for http type only)
2650-
authHelper = this.getAuthHelper(openapi, operation.security);
2652+
if (!options.alwaysInheritAuthentication) {
2653+
authHelper = this.getAuthHelper(openapi, operation.security);
2654+
}
26512655

26522656
// creating the request object
26532657
item = new sdk.Item({

lib/schemapack.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
'use strict';
22

3-
// This is the default collection name if one can't be inferred from the OpenAPI spec
4-
const COLLECTION_NAME = 'Imported from OpenAPI 3.0',
5-
{ getConcreteSchemaUtils } = require('./common/versionUtils.js'),
3+
const { getConcreteSchemaUtils } = require('./common/versionUtils.js'),
64
{ convertToOAS30IfSwagger } = require('./swaggerUtils/swaggerToOpenapi.js'),
75
BROWSER = 'browser',
86
Ajv = require('ajv'),
@@ -194,12 +192,14 @@ class SchemaPack {
194192
}
195193
// if the schema is validated, return the meta data as required.
196194
else if (this.validated) {
195+
let name = utils.getCollectionName(_.get(this.openapi, 'info.title'));
196+
197197
return cb(null, {
198198
result: true,
199-
name: _.get(this.openapi, 'info.title', COLLECTION_NAME),
199+
name: name,
200200
output: [{
201201
type: 'collection',
202-
name: _.get(this.openapi, 'info.title', COLLECTION_NAME)
202+
name: name
203203
}]
204204
});
205205
}
@@ -213,12 +213,14 @@ class SchemaPack {
213213
return cb(null, validationResult);
214214
}
215215

216+
let name = utils.getCollectionName(_.get(this.openapi, 'info.title'));
217+
216218
return cb(null, {
217219
result: true,
218-
name: _.get(this.openapi, 'info.title', COLLECTION_NAME),
220+
name: name,
219221
output: [{
220222
type: 'collection',
221-
name: _.get(this.openapi, 'info.title', COLLECTION_NAME)
223+
name: name
222224
}]
223225
});
224226
});
@@ -340,7 +342,7 @@ class SchemaPack {
340342
// All generated folders and requests will go inside this
341343
generatedStore.collection = new sdk.Collection({
342344
info: {
343-
name: _.isEmpty(_.get(openapi, 'info.title')) ? COLLECTION_NAME : _.get(openapi, 'info.title')
345+
name: utils.getCollectionName(_.get(openapi, 'info.title'))
344346
}
345347
});
346348

lib/utils.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
const _ = require('lodash');
1+
const _ = require('lodash'),
2+
3+
// This is the default collection name if one can't be inferred from the OpenAPI spec
4+
COLLECTION_NAME = 'Imported from OpenAPI';
25

36
// this will have non-OAS-related utils
47

@@ -142,5 +145,19 @@ module.exports = {
142145
res.push(segment);
143146
}
144147
return res.join('/');
148+
},
149+
150+
/**
151+
* Provides collection name to be used for generated collection
152+
*
153+
* @param {*} title - Definition title
154+
* @returns {String} - Collection name
155+
*/
156+
getCollectionName: function (title) {
157+
if (_.isEmpty(title) || !_.isString(title)) {
158+
return COLLECTION_NAME;
159+
}
160+
161+
return title;
145162
}
146163
};

lib/xmlSchemaFaker.js

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
/* eslint-disable */
2-
const _ = require('lodash');
2+
const _ = require('lodash'),
3+
js2xml = require('../lib/common/js2xml');
34

4-
function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
5+
function indentContent (content, initialIndent) {
6+
let contentArr = _.split(content, '\n'),
7+
indentedContent = _.join(_.map(contentArr, (contentElement) => { return initialIndent + contentElement; }), '\n');
8+
9+
return indentedContent;
10+
}
11+
12+
function convertSchemaToXML(name, schema, attribute, indentChar, indent, resolveTo) {
513
var tagPrefix = '',
6-
cIndent = _.times(indent, _.constant(indentChar)).join('');
14+
cIndent = _.times(indent, _.constant(indentChar)).join(''),
15+
retVal = '';
16+
17+
const schemaExample = typeof schema === 'object' && (schema.example);
18+
719
name = _.get(schema, 'xml.name', name || 'element');
820
if (_.get(schema, 'xml.prefix')) {
921
tagPrefix = schema.xml.prefix ? `${schema.xml.prefix}:` : '';
@@ -21,53 +33,81 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
2133
else if (schema.type === 'number') {
2234
actualValue = '(number)';
2335
}
36+
37+
if (resolveTo === 'example' && typeof schemaExample !== 'undefined') {
38+
actualValue = schemaExample;
39+
}
40+
2441
if (attribute) {
2542
return actualValue;
2643
}
2744
else {
28-
var retVal = `\n${cIndent}<${tagPrefix+name}`;
45+
retVal = `\n${cIndent}<${tagPrefix+name}`;
2946
if (_.get(schema, 'xml.namespace')) {
3047
retVal += ` xmlns:${tagPrefix.slice(0,-1)}="${schema.xml.namespace}"`
3148
}
3249
retVal += `>${actualValue}</${tagPrefix}${name}>`;
3350
}
3451
}
3552
else if (schema.type === 'object') {
36-
// go through all properties
37-
var retVal = '\n' + cIndent + `<${tagPrefix}${name}`, propVal, attributes = [], childNodes = '';
38-
if (_.get(schema, 'xml.namespace')) {
39-
let formattedTagPrefix = tagPrefix ?
40-
`:${tagPrefix.slice(0,-1)}` :
41-
'';
42-
retVal += ` xmlns${formattedTagPrefix}="${schema.xml.namespace}"`
53+
if (resolveTo === 'example' && typeof schemaExample !== 'undefined') {
54+
const elementName = _.get(schema, 'items.xml.name', name || 'element'),
55+
fakedContent = js2xml({ [elementName]: schemaExample }, indentChar);
56+
57+
retVal = '\n' + indentContent(fakedContent, cIndent);
4358
}
44-
_.forOwn(schema.properties, (value, key) => {
45-
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1);
46-
if (_.get(value, 'xml.attribute')) {
47-
attributes.push(`${key}="${propVal}"`);
59+
else {
60+
// go through all properties
61+
var propVal, attributes = [], childNodes = '';
62+
63+
retVal = '\n' + cIndent + `<${tagPrefix}${name}`;
64+
65+
if (_.get(schema, 'xml.namespace')) {
66+
let formattedTagPrefix = tagPrefix ?
67+
`:${tagPrefix.slice(0,-1)}` :
68+
'';
69+
retVal += ` xmlns${formattedTagPrefix}="${schema.xml.namespace}"`
4870
}
49-
else {
50-
childNodes += _.isString(propVal) ? propVal : '';
71+
_.forOwn(schema.properties, (value, key) => {
72+
propVal = convertSchemaToXML(key, value, _.get(value, 'xml.attribute'), indentChar, indent + 1, resolveTo);
73+
if (_.get(value, 'xml.attribute')) {
74+
attributes.push(`${key}="${propVal}"`);
75+
}
76+
else {
77+
childNodes += _.isString(propVal) ? propVal : '';
78+
}
79+
});
80+
if (attributes.length > 0) {
81+
retVal += ' ' + attributes.join(' ');
5182
}
52-
});
53-
if (attributes.length > 0) {
54-
retVal += ' ' + attributes.join(' ');
83+
retVal += '>';
84+
retVal += childNodes;
85+
retVal += `\n${cIndent}</${tagPrefix}${name}>`;
5586
}
56-
retVal += '>';
57-
retVal += childNodes;
58-
retVal += `\n${cIndent}</${tagPrefix}${name}>`;
5987
}
6088
else if (schema.type === 'array') {
6189
// schema.items must be an object
6290
var isWrapped = _.get(schema, 'xml.wrapped'),
6391
extraIndent = isWrapped ? 1 : 0,
64-
arrayElemName = _.get(schema, 'items.xml.name', name, 'arrayItem'),
92+
arrayElemName = _.get(schema, 'items.xml.name', name || 'element'),
6593
schemaItemsWithXmlProps = _.cloneDeep(schema.items),
6694
contents;
6795

6896
schemaItemsWithXmlProps.xml = schema.xml;
69-
contents = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent) +
70-
convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar, indent + extraIndent);
97+
98+
if (resolveTo === 'example' && typeof schemaExample !== 'undefined') {
99+
const fakedContent = js2xml({ [arrayElemName]: schemaExample }, indentChar);
100+
101+
contents = '\n' + indentContent(fakedContent, cIndent);
102+
}
103+
else {
104+
let singleElementContent = convertSchemaToXML(arrayElemName, schemaItemsWithXmlProps, false, indentChar,
105+
indent + extraIndent, resolveTo);
106+
107+
// Atleast 2 items per array will be added asame as JSON schema faker
108+
contents = singleElementContent + singleElementContent;
109+
}
110+
71111
if (isWrapped) {
72112
return `\n${cIndent}<${tagPrefix}${name}>${contents}\n${cIndent}</${tagPrefix}${name}>`;
73113
}
@@ -78,9 +118,9 @@ function convertSchemaToXML(name, schema, attribute, indentChar, indent) {
78118
return retVal;
79119
}
80120

81-
module.exports = function(name, schema, indentCharacter) {
121+
module.exports = function(name, schema, indentCharacter, resolveTo) {
82122
// substring(1) to trim the leading newline
83-
return convertSchemaToXML(name, schema, false, indentCharacter, 0).substring(1);
123+
return convertSchemaToXML(name, schema, false, indentCharacter, 0, resolveTo).substring(1);
84124
};
85125
/*
86126
a = convertSchemaToXML('Person',{

libV2/helpers/collection/generateCollectionFromOpenAPI.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const _ = require('lodash'),
2+
utils = require('../../utils'),
23
generateAuthrForCollectionFromOpenAPI = require('./generateAuthForCollectionFromOpenAPI'),
3-
COLLECTION_NAME = 'Imported from OpenAPI 3.0',
44

55
/**
66
* Returns a description that's usable at the collection-level
@@ -96,7 +96,7 @@ module.exports = function ({ openapi }) {
9696
return {
9797
data: {
9898
info: {
99-
name: _.get(openapi, 'info.title', COLLECTION_NAME),
99+
name: utils.getCollectionName(_.get(openapi, 'info.title')),
100100
description: getCollectionDescription(openapi)
101101
},
102102
auth: generateAuthrForCollectionFromOpenAPI(openapi, openapi.security)

0 commit comments

Comments
 (0)