mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
Refactor rule resolver 3.0 and 3.1
- Moving each bundling version rules to new files - Removing componentsParentMatcher files - Replacing the getKeyInComponents for each version by a generalized one - Adding a method to get the version bundling data by version - Replacing the new sources in files
This commit is contained in:
@@ -1,102 +0,0 @@
|
|||||||
const COMPONENTS_KEYS_30 = [
|
|
||||||
'schemas',
|
|
||||||
'responses',
|
|
||||||
'parameters',
|
|
||||||
'examples',
|
|
||||||
'requestBodies',
|
|
||||||
'headers',
|
|
||||||
'securitySchemes',
|
|
||||||
'links',
|
|
||||||
'callbacks'
|
|
||||||
],
|
|
||||||
SCHEMA_CONTAINERS = [
|
|
||||||
'allOf',
|
|
||||||
'oneOf',
|
|
||||||
'anyOf',
|
|
||||||
'not',
|
|
||||||
'additionalProperties',
|
|
||||||
'items',
|
|
||||||
'schema'
|
|
||||||
],
|
|
||||||
EXAMPLE_CONTAINERS = [
|
|
||||||
'example'
|
|
||||||
],
|
|
||||||
PROPERTY_DEFINITION = [
|
|
||||||
'properties'
|
|
||||||
],
|
|
||||||
RESPONSE_DEFINITION = [
|
|
||||||
'responses'
|
|
||||||
],
|
|
||||||
REQUEST_BODY_CONTAINER = [
|
|
||||||
'requestBody'
|
|
||||||
],
|
|
||||||
LINKS_CONTAINER = [
|
|
||||||
'links'
|
|
||||||
],
|
|
||||||
HEADER_DEFINITION = [
|
|
||||||
'headers'
|
|
||||||
],
|
|
||||||
CALLBACK_DEFINITION = [
|
|
||||||
'callbacks'
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
/**
|
|
||||||
* Generates the trace to the key that will wrap de component using 3.0 version
|
|
||||||
* @param {array} traceFromParent - The trace from the parent key
|
|
||||||
* @param {string} filePathName - The filePath name from the file
|
|
||||||
* @param {string} localPart - The local path part
|
|
||||||
* @param {function} jsonPointerDecodeAndReplace - Function to decode a json pointer
|
|
||||||
* @returns {array} The trace to the container key
|
|
||||||
*/
|
|
||||||
getKeyInComponents30: function (traceFromParent, filePathName, localPart, jsonPointerDecodeAndReplace) {
|
|
||||||
let res = traceFromParent,
|
|
||||||
trace = [],
|
|
||||||
traceToKey = [],
|
|
||||||
matchFound = false,
|
|
||||||
isInComponents = traceFromParent[0] === 'components';
|
|
||||||
|
|
||||||
if (isInComponents) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
res.push(jsonPointerDecodeAndReplace(`${filePathName}${localPart}`));
|
|
||||||
trace = [...res].reverse();
|
|
||||||
|
|
||||||
for (let [index, item] of trace.entries()) {
|
|
||||||
if (SCHEMA_CONTAINERS.includes(item)) {
|
|
||||||
item = 'schemas';
|
|
||||||
}
|
|
||||||
if (EXAMPLE_CONTAINERS.includes(item)) {
|
|
||||||
item = 'examples';
|
|
||||||
}
|
|
||||||
if (REQUEST_BODY_CONTAINER.includes(item)) {
|
|
||||||
item = 'requestBodies';
|
|
||||||
}
|
|
||||||
if (LINKS_CONTAINER.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'links';
|
|
||||||
}
|
|
||||||
if (PROPERTY_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'schemas';
|
|
||||||
}
|
|
||||||
traceToKey.push(item);
|
|
||||||
if (COMPONENTS_KEYS_30.includes(item)) {
|
|
||||||
matchFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (RESPONSE_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'responses';
|
|
||||||
}
|
|
||||||
if (HEADER_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'headers';
|
|
||||||
}
|
|
||||||
if (CALLBACK_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'callbacks';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matchFound ?
|
|
||||||
traceToKey.reverse() :
|
|
||||||
[];
|
|
||||||
},
|
|
||||||
COMPONENTS_KEYS_30
|
|
||||||
};
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
const COMPONENTS_KEYS_31 = [
|
|
||||||
'schemas',
|
|
||||||
'responses',
|
|
||||||
'parameters',
|
|
||||||
'examples',
|
|
||||||
'requestBodies',
|
|
||||||
'headers',
|
|
||||||
'securitySchemes',
|
|
||||||
'links',
|
|
||||||
'callbacks',
|
|
||||||
'pathItems'
|
|
||||||
],
|
|
||||||
SCHEMA_CONTAINERS = [
|
|
||||||
'allOf',
|
|
||||||
'oneOf',
|
|
||||||
'anyOf',
|
|
||||||
'not',
|
|
||||||
'additionalProperties',
|
|
||||||
'items',
|
|
||||||
'schema'
|
|
||||||
],
|
|
||||||
EXAMPLE_CONTAINERS = [
|
|
||||||
'example'
|
|
||||||
],
|
|
||||||
PROPERTY_DEFINITION = [
|
|
||||||
'properties'
|
|
||||||
],
|
|
||||||
RESPONSE_DEFINITION = [
|
|
||||||
'responses'
|
|
||||||
],
|
|
||||||
REQUEST_BODY_CONTAINER = [
|
|
||||||
'requestBody'
|
|
||||||
],
|
|
||||||
LINKS_CONTAINER = [
|
|
||||||
'links'
|
|
||||||
],
|
|
||||||
HEADER_DEFINITION = [
|
|
||||||
'headers'
|
|
||||||
],
|
|
||||||
CALLBACK_DEFINITION = [
|
|
||||||
'callbacks'
|
|
||||||
],
|
|
||||||
PATH_ITEM_CONTAINER = [
|
|
||||||
'paths'
|
|
||||||
];
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
/**
|
|
||||||
* Generates the trace to the key that will wrap de component using 3.0 version
|
|
||||||
* @param {array} traceFromParent - The trace from the parent key
|
|
||||||
* @param {string} filePathName - The filePath name from the file
|
|
||||||
* @param {string} localPart - The local path part
|
|
||||||
* @param {function} jsonPointerDecodeAndReplace - Function to decode a json pointer
|
|
||||||
* @returns {array} The trace to the container key
|
|
||||||
*/
|
|
||||||
getKeyInComponents31: function (traceFromParent, filePathName, localPart, jsonPointerDecodeAndReplace) {
|
|
||||||
let res = traceFromParent,
|
|
||||||
trace = [],
|
|
||||||
traceToKey = [],
|
|
||||||
matchFound = false,
|
|
||||||
isInComponents = traceFromParent[0] === 'components';
|
|
||||||
|
|
||||||
if (isInComponents) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
res.push(jsonPointerDecodeAndReplace(`${filePathName}${localPart}`));
|
|
||||||
trace = [...res].reverse();
|
|
||||||
|
|
||||||
for (let [index, item] of trace.entries()) {
|
|
||||||
if (SCHEMA_CONTAINERS.includes(item)) {
|
|
||||||
item = 'schemas';
|
|
||||||
}
|
|
||||||
if (EXAMPLE_CONTAINERS.includes(item)) {
|
|
||||||
item = 'examples';
|
|
||||||
}
|
|
||||||
if (REQUEST_BODY_CONTAINER.includes(item)) {
|
|
||||||
item = 'requestBodies';
|
|
||||||
}
|
|
||||||
if (LINKS_CONTAINER.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'links';
|
|
||||||
}
|
|
||||||
if (PATH_ITEM_CONTAINER.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'pathItems';
|
|
||||||
}
|
|
||||||
if (PROPERTY_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'schemas';
|
|
||||||
}
|
|
||||||
traceToKey.push(item);
|
|
||||||
if (COMPONENTS_KEYS_31.includes(item)) {
|
|
||||||
matchFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (RESPONSE_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'responses';
|
|
||||||
}
|
|
||||||
if (HEADER_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'headers';
|
|
||||||
}
|
|
||||||
if (CALLBACK_DEFINITION.includes(trace[index + 2])) {
|
|
||||||
trace[index + 1] = 'callbacks';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matchFound ?
|
|
||||||
traceToKey.reverse() :
|
|
||||||
[];
|
|
||||||
},
|
|
||||||
COMPONENTS_KEYS_31
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
const { COMPONENTS_KEYS_30 } = require('./30XUtils/componentsParentMatcher'),
|
const {
|
||||||
{
|
|
||||||
isExtRef,
|
isExtRef,
|
||||||
getKeyInComponents,
|
getKeyInComponents,
|
||||||
getJsonPointerRelationToRoot,
|
getJsonPointerRelationToRoot,
|
||||||
@@ -11,8 +10,8 @@ const { COMPONENTS_KEYS_30 } = require('./30XUtils/componentsParentMatcher'),
|
|||||||
} = require('./jsonPointer'),
|
} = require('./jsonPointer'),
|
||||||
traverseUtility = require('traverse'),
|
traverseUtility = require('traverse'),
|
||||||
parse = require('./parse.js'),
|
parse = require('./parse.js'),
|
||||||
{ COMPONENTS_KEYS_31 } = require('./31XUtils/componentsParentMatcher'),
|
|
||||||
{ ParseError } = require('./common/ParseError');
|
{ ParseError } = require('./common/ParseError');
|
||||||
|
const { getBundleRulesDataByVersion } = require('./common/versionUtils');
|
||||||
|
|
||||||
let path = require('path'),
|
let path = require('path'),
|
||||||
pathBrowserify = require('path-browserify'),
|
pathBrowserify = require('path-browserify'),
|
||||||
@@ -156,7 +155,7 @@ function getContentFromTrace(content, partial) {
|
|||||||
* @returns {null} It modifies components global context
|
* @returns {null} It modifies components global context
|
||||||
*/
|
*/
|
||||||
function setValueInComponents(keyInComponents, components, value, version) {
|
function setValueInComponents(keyInComponents, components, value, version) {
|
||||||
const COMPONENTS_KEYS = version === '3.1' ? COMPONENTS_KEYS_31 : COMPONENTS_KEYS_30;
|
const { COMPONENTS_KEYS } = getBundleRulesDataByVersion(version);
|
||||||
let currentPlace = components,
|
let currentPlace = components,
|
||||||
target = keyInComponents[keyInComponents.length - 2],
|
target = keyInComponents[keyInComponents.length - 2],
|
||||||
key = keyInComponents.length === 2 && COMPONENTS_KEYS.includes(keyInComponents[0]) ?
|
key = keyInComponents.length === 2 && COMPONENTS_KEYS.includes(keyInComponents[0]) ?
|
||||||
|
|||||||
33
lib/bundleRules/resolvers.js
Normal file
33
lib/bundleRules/resolvers.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* Resolve the scenario if the item is in second level
|
||||||
|
* @param {array} trace The keyInComponents
|
||||||
|
* @param {number} index the current index
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
|
||||||
|
resolveSecondLevelChild: function (trace, index, definitions) {
|
||||||
|
const item = definitions[trace[index + 2]];
|
||||||
|
if (item) {
|
||||||
|
trace[index + 1] = item;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the provided item is included in any defined container it returns the container name
|
||||||
|
* else it return the same item
|
||||||
|
* @param {string} item The current item in the iteration
|
||||||
|
* @returns {string} the name of container where item is included or the item if it's not included
|
||||||
|
* in any container
|
||||||
|
*/
|
||||||
|
|
||||||
|
resolveFirstLevelChild: function(item, containers) {
|
||||||
|
for (let [key, containerItems] of Object.entries(containers)) {
|
||||||
|
if (containerItems.includes(item)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
};
|
||||||
52
lib/bundleRules/spec30.js
Normal file
52
lib/bundleRules/spec30.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const SCHEMA_CONTAINERS = [
|
||||||
|
'allOf',
|
||||||
|
'oneOf',
|
||||||
|
'anyOf',
|
||||||
|
'not',
|
||||||
|
'additionalProperties',
|
||||||
|
'items',
|
||||||
|
'schema'
|
||||||
|
],
|
||||||
|
EXAMPLE_CONTAINERS = [
|
||||||
|
'example'
|
||||||
|
],
|
||||||
|
REQUEST_BODY_CONTAINER = [
|
||||||
|
'requestBody'
|
||||||
|
],
|
||||||
|
CONTAINERS = {
|
||||||
|
schemas: SCHEMA_CONTAINERS,
|
||||||
|
examples: EXAMPLE_CONTAINERS,
|
||||||
|
requestBodies: REQUEST_BODY_CONTAINER
|
||||||
|
},
|
||||||
|
DEFINITIONS = {
|
||||||
|
headers: 'headers',
|
||||||
|
responses: 'responses',
|
||||||
|
callbacks: 'callbacks',
|
||||||
|
properties: 'schemas',
|
||||||
|
links: 'links'
|
||||||
|
},
|
||||||
|
INLINE = [],
|
||||||
|
ROOT_CONTAINERS_KEYS = [
|
||||||
|
'components'
|
||||||
|
],
|
||||||
|
COMPONENTS_KEYS = [
|
||||||
|
'schemas',
|
||||||
|
'responses',
|
||||||
|
'parameters',
|
||||||
|
'examples',
|
||||||
|
'requestBodies',
|
||||||
|
'headers',
|
||||||
|
'securitySchemes',
|
||||||
|
'links',
|
||||||
|
'callbacks'
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
RULES_30: {
|
||||||
|
CONTAINERS,
|
||||||
|
DEFINITIONS,
|
||||||
|
COMPONENTS_KEYS,
|
||||||
|
INLINE,
|
||||||
|
ROOT_CONTAINERS_KEYS
|
||||||
|
}
|
||||||
|
};
|
||||||
54
lib/bundleRules/spec31.js
Normal file
54
lib/bundleRules/spec31.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
const SCHEMA_CONTAINERS = [
|
||||||
|
'allOf',
|
||||||
|
'oneOf',
|
||||||
|
'anyOf',
|
||||||
|
'not',
|
||||||
|
'additionalProperties',
|
||||||
|
'items',
|
||||||
|
'schema'
|
||||||
|
],
|
||||||
|
EXAMPLE_CONTAINERS = [
|
||||||
|
'example'
|
||||||
|
],
|
||||||
|
REQUEST_BODY_CONTAINER = [
|
||||||
|
'requestBody'
|
||||||
|
],
|
||||||
|
CONTAINERS = {
|
||||||
|
schemas: SCHEMA_CONTAINERS,
|
||||||
|
examples: EXAMPLE_CONTAINERS,
|
||||||
|
requestBodies: REQUEST_BODY_CONTAINER
|
||||||
|
},
|
||||||
|
DEFINITIONS = {
|
||||||
|
headers: 'headers',
|
||||||
|
responses: 'responses',
|
||||||
|
callbacks: 'callbacks',
|
||||||
|
properties: 'schemas',
|
||||||
|
links: 'links',
|
||||||
|
paths: 'pathItems'
|
||||||
|
},
|
||||||
|
INLINE = [],
|
||||||
|
ROOT_CONTAINERS_KEYS = [
|
||||||
|
'components'
|
||||||
|
],
|
||||||
|
COMPONENTS_KEYS = [
|
||||||
|
'schemas',
|
||||||
|
'responses',
|
||||||
|
'parameters',
|
||||||
|
'examples',
|
||||||
|
'requestBodies',
|
||||||
|
'headers',
|
||||||
|
'securitySchemes',
|
||||||
|
'links',
|
||||||
|
'callbacks',
|
||||||
|
'pathItems'
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
RULES_31: {
|
||||||
|
CONTAINERS,
|
||||||
|
DEFINITIONS,
|
||||||
|
COMPONENTS_KEYS,
|
||||||
|
INLINE,
|
||||||
|
ROOT_CONTAINERS_KEYS
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -6,7 +6,9 @@ const VERSION_30 = { key: 'openapi', version: '3.0' },
|
|||||||
DEFAULT_SPEC_VERSION = VERSION_30.version,
|
DEFAULT_SPEC_VERSION = VERSION_30.version,
|
||||||
SWAGGER_VERSION = VERSION_20.version,
|
SWAGGER_VERSION = VERSION_20.version,
|
||||||
VERSION_3_1 = VERSION_31.version,
|
VERSION_3_1 = VERSION_31.version,
|
||||||
fs = require('fs');
|
fs = require('fs'),
|
||||||
|
{ RULES_30 } = require('./../bundleRules/spec30'),
|
||||||
|
{ RULES_31 } = require('./../bundleRules/spec31');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets the version key and the version and generates a regular expression that
|
* gets the version key and the version and generates a regular expression that
|
||||||
@@ -268,6 +270,21 @@ function validateSupportedVersion(version) {
|
|||||||
return isValid !== undefined;
|
return isValid !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bundling rules to follow in the bundling process
|
||||||
|
* @param {string} version The spec version we are bundling
|
||||||
|
* @returns {object} The bundling rules related with the spec
|
||||||
|
*/
|
||||||
|
function getBundleRulesDataByVersion(version) {
|
||||||
|
const is31 = compareVersion(version, VERSION_31.version);
|
||||||
|
if (is31) {
|
||||||
|
return RULES_31;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return RULES_30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getSpecVersion,
|
getSpecVersion,
|
||||||
getConcreteSchemaUtils,
|
getConcreteSchemaUtils,
|
||||||
@@ -277,5 +294,6 @@ module.exports = {
|
|||||||
getVersionRegexBySpecificationVersion,
|
getVersionRegexBySpecificationVersion,
|
||||||
SWAGGER_VERSION,
|
SWAGGER_VERSION,
|
||||||
VERSION_3_1,
|
VERSION_3_1,
|
||||||
validateSupportedVersion
|
validateSupportedVersion,
|
||||||
|
getBundleRulesDataByVersion
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ const slashes = /\//g,
|
|||||||
escapedTilde = /~0/g,
|
escapedTilde = /~0/g,
|
||||||
jsonPointerLevelSeparator = '/',
|
jsonPointerLevelSeparator = '/',
|
||||||
escapedTildeString = '~0',
|
escapedTildeString = '~0',
|
||||||
{ getKeyInComponents30 } = require('./30XUtils/componentsParentMatcher'),
|
{ getBundleRulesDataByVersion } = require('./common/versionUtils'),
|
||||||
{ getKeyInComponents31 } = require('./31XUtils/componentsParentMatcher'),
|
{
|
||||||
{ VERSION_3_1 } = require('./common/versionUtils');
|
resolveFirstLevelChild,
|
||||||
|
resolveSecondLevelChild
|
||||||
|
} = require('./bundleRules/resolvers');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a filepath name so it can be a json pointer
|
* Encodes a filepath name so it can be a json pointer
|
||||||
@@ -51,15 +53,44 @@ function jsonPointerDecodeAndReplace(filePathName) {
|
|||||||
*/
|
*/
|
||||||
function getKeyInComponents(traceFromParent, filePathName, localPath, version) {
|
function getKeyInComponents(traceFromParent, filePathName, localPath, version) {
|
||||||
const localPart = localPath ? `${localPointer}${localPath}` : '',
|
const localPart = localPath ? `${localPointer}${localPath}` : '',
|
||||||
is31 = version === VERSION_3_1;
|
{
|
||||||
let result;
|
CONTAINERS,
|
||||||
|
DEFINITIONS,
|
||||||
|
COMPONENTS_KEYS,
|
||||||
|
INLINE,
|
||||||
|
ROOT_CONTAINERS_KEYS
|
||||||
|
} = getBundleRulesDataByVersion(version);
|
||||||
|
let result,
|
||||||
|
trace = [
|
||||||
|
...traceFromParent,
|
||||||
|
jsonPointerDecodeAndReplace(`${filePathName}${localPart}`)
|
||||||
|
].reverse(),
|
||||||
|
traceToKey = [],
|
||||||
|
matchFound = false,
|
||||||
|
isRootAndReusableItemsContainer = ROOT_CONTAINERS_KEYS.includes(traceFromParent[0]);
|
||||||
|
|
||||||
if (is31) {
|
if (isRootAndReusableItemsContainer) {
|
||||||
result = getKeyInComponents31(traceFromParent, filePathName, localPart, jsonPointerDecodeAndReplace);
|
return [];
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
result = getKeyInComponents30(traceFromParent, filePathName, localPart, jsonPointerDecodeAndReplace);
|
for (let [index, item] of trace.entries()) {
|
||||||
|
let itemShouldBeResolvedInline = INLINE.includes(item);
|
||||||
|
|
||||||
|
if (itemShouldBeResolvedInline) {
|
||||||
|
matchFound = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
item = resolveFirstLevelChild(item, CONTAINERS);
|
||||||
|
resolveSecondLevelChild(trace, index, DEFINITIONS);
|
||||||
|
traceToKey.push(item);
|
||||||
|
if (COMPONENTS_KEYS.includes(item)) {
|
||||||
|
matchFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
result = matchFound ?
|
||||||
|
traceToKey.reverse() :
|
||||||
|
[];
|
||||||
return result.map(generateObjectName);
|
return result.map(generateObjectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user