mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
merge
merge
This commit is contained in:
114
lib/bundle.js
114
lib/bundle.js
@@ -6,13 +6,15 @@ const {
|
|||||||
localPointer,
|
localPointer,
|
||||||
jsonPointerLevelSeparator,
|
jsonPointerLevelSeparator,
|
||||||
isLocalRef,
|
isLocalRef,
|
||||||
jsonPointerDecodeAndReplace
|
jsonPointerDecodeAndReplace,
|
||||||
|
generateObjectName
|
||||||
} = require('./jsonPointer'),
|
} = require('./jsonPointer'),
|
||||||
traverseUtility = require('traverse'),
|
traverseUtility = require('traverse'),
|
||||||
parse = require('./parse.js'),
|
parse = require('./parse.js'),
|
||||||
{ ParseError } = require('./common/ParseError');
|
{ ParseError } = require('./common/ParseError'),
|
||||||
const { getBundleRulesDataByVersion } = require('./common/versionUtils'),
|
Utils = require('./utils'),
|
||||||
Utils = require('./utils');
|
crypto = require('crypto'),
|
||||||
|
{ getBundleRulesDataByVersion } = require('./common/versionUtils');
|
||||||
|
|
||||||
let path = require('path'),
|
let path = require('path'),
|
||||||
pathBrowserify = require('path-browserify'),
|
pathBrowserify = require('path-browserify'),
|
||||||
@@ -184,15 +186,45 @@ function setValueInComponents(keyInComponents, components, value, version) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the has of a provided key and join its first 4 numbers at the end of the current key by a _
|
||||||
|
* @param {string} currentKey The key we will hash
|
||||||
|
* @returns {string} A key with a hashed part joined by _
|
||||||
|
*/
|
||||||
|
function createComponentHashedKey(currentKey) {
|
||||||
|
let hashPart = crypto.createHash('sha1')
|
||||||
|
.update(currentKey)
|
||||||
|
.digest('base64')
|
||||||
|
.substring(0, 4),
|
||||||
|
newKey = generateObjectName(currentKey, hashPart);
|
||||||
|
return newKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a not repeated mainKey for the component
|
||||||
|
* @param {string} tempRef - The reference to the node we are processing
|
||||||
|
* @param {array} mainKeys - A list of previous generated mainKeys
|
||||||
|
* @returns {string} A generated mainKey from the provided tempRef
|
||||||
|
*/
|
||||||
|
function createComponentMainKey(tempRef, mainKeys) {
|
||||||
|
let newKey = generateObjectName(tempRef),
|
||||||
|
mainKey = mainKeys[newKey];
|
||||||
|
if (mainKey && mainKey !== tempRef) {
|
||||||
|
newKey = createComponentHashedKey(tempRef);
|
||||||
|
}
|
||||||
|
return newKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a trace from the current node's root to the place where we find a $ref
|
* Return a trace from the current node's root to the place where we find a $ref
|
||||||
* @param {object} nodeContext - The current node we are processing
|
* @param {object} nodeContext - The current node we are processing
|
||||||
* @param {object} property - The current property that contains the $ref
|
* @param {object} tempRef - The tempRef from the $ref
|
||||||
|
* @param {object} mainKeys - The dictionary of the previous keys generated
|
||||||
* @param {string} version - The current version of the spec
|
* @param {string} version - The current version of the spec
|
||||||
* @param {string} commonPathFromData - The common path in the file's paths
|
* @param {string} commonPathFromData - The common path in the file's paths
|
||||||
* @returns {array} The trace to the place where the $ref appears
|
* @returns {array} The trace to the place where the $ref appears
|
||||||
*/
|
*/
|
||||||
function getTraceFromParentKeyInComponents(nodeContext, property, version, commonPathFromData) {
|
function getTraceFromParentKeyInComponents(nodeContext, tempRef, mainKeys, version, commonPathFromData) {
|
||||||
const parents = [...nodeContext.parents].reverse(),
|
const parents = [...nodeContext.parents].reverse(),
|
||||||
isArrayKeyRegexp = new RegExp('^\\d$', 'g'),
|
isArrayKeyRegexp = new RegExp('^\\d$', 'g'),
|
||||||
key = nodeContext.key,
|
key = nodeContext.key,
|
||||||
@@ -204,11 +236,31 @@ function getTraceFromParentKeyInComponents(nodeContext, property, version, commo
|
|||||||
parentKeys :
|
parentKeys :
|
||||||
[key, ...parentKeys],
|
[key, ...parentKeys],
|
||||||
nodeTrace = getRootFileTrace(nodeParentsKey),
|
nodeTrace = getRootFileTrace(nodeParentsKey),
|
||||||
[file, local] = property.split(localPointer),
|
componentKey = createComponentMainKey(tempRef, mainKeys),
|
||||||
keyTraceInComponents = getKeyInComponents(nodeTrace, file, local, version, commonPathFromData);
|
keyTraceInComponents = getKeyInComponents(nodeTrace, componentKey, version, commonPathFromData);
|
||||||
return keyTraceInComponents;
|
return keyTraceInComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the generated trace if there is a collision with a key that exists in root components object
|
||||||
|
* @param {array} trace The generated trace
|
||||||
|
* @param {object} initialMainKeys the main keys in local components object if it exists
|
||||||
|
* @returns {array} A modified trace if there is any collision with local reusable objects
|
||||||
|
*/
|
||||||
|
function handleLocalCollisions(trace, initialMainKeys) {
|
||||||
|
if (trace.length === 0) {
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
const componentType = trace[trace.length - 2],
|
||||||
|
initialKeysOfType = initialMainKeys[componentType],
|
||||||
|
generatedKeyIndex = trace.length - 1;
|
||||||
|
|
||||||
|
if (initialKeysOfType && initialKeysOfType.includes(trace[generatedKeyIndex])) {
|
||||||
|
trace[generatedKeyIndex] = createComponentHashedKey(trace[generatedKeyIndex]);
|
||||||
|
}
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all the $refs from an object
|
* Gets all the $refs from an object
|
||||||
* @param {object} currentNode - current node in process
|
* @param {object} currentNode - current node in process
|
||||||
@@ -216,12 +268,15 @@ function getTraceFromParentKeyInComponents(nodeContext, property, version, commo
|
|||||||
* @param {Function} pathSolver - function to resolve the Path
|
* @param {Function} pathSolver - function to resolve the Path
|
||||||
* @param {string} parentFilename - The parent's filename
|
* @param {string} parentFilename - The parent's filename
|
||||||
* @param {object} version - The version of the spec we are bundling
|
* @param {object} version - The version of the spec we are bundling
|
||||||
|
* @param {object} rootMainKeys - A dictionary with the component keys in local components object and its mainKeys
|
||||||
* @param {string} commonPathFromData - The common path in the file's paths
|
* @param {string} commonPathFromData - The common path in the file's paths
|
||||||
* @returns {object} - The references in current node and the new content from the node
|
* @returns {object} - The references in current node and the new content from the node
|
||||||
*/
|
*/
|
||||||
function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, commonPathFromData) {
|
function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, rootMainKeys,
|
||||||
|
commonPathFromData) {
|
||||||
let referencesInNode = [],
|
let referencesInNode = [],
|
||||||
nodeReferenceDirectory = {};
|
nodeReferenceDirectory = {},
|
||||||
|
mainKeys = {};
|
||||||
traverseUtility(currentNode).forEach(function (property) {
|
traverseUtility(currentNode).forEach(function (property) {
|
||||||
if (property) {
|
if (property) {
|
||||||
let hasReferenceTypeKey;
|
let hasReferenceTypeKey;
|
||||||
@@ -236,7 +291,12 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
|
|||||||
);
|
);
|
||||||
if (hasReferenceTypeKey) {
|
if (hasReferenceTypeKey) {
|
||||||
const tempRef = calculatePath(parentFilename, property.$ref),
|
const tempRef = calculatePath(parentFilename, property.$ref),
|
||||||
nodeTrace = getTraceFromParentKeyInComponents(this, tempRef, version, commonPathFromData),
|
nodeTrace = handleLocalCollisions(
|
||||||
|
getTraceFromParentKeyInComponents(this, tempRef, mainKeys, version),
|
||||||
|
rootMainKeys,
|
||||||
|
commonPathFromData
|
||||||
|
),
|
||||||
|
componentKey = nodeTrace[nodeTrace.length - 1],
|
||||||
referenceInDocument = getJsonPointerRelationToRoot(
|
referenceInDocument = getJsonPointerRelationToRoot(
|
||||||
tempRef,
|
tempRef,
|
||||||
nodeTrace,
|
nodeTrace,
|
||||||
@@ -261,9 +321,12 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
|
|||||||
node: newValue,
|
node: newValue,
|
||||||
reference: referenceInDocument,
|
reference: referenceInDocument,
|
||||||
traceToParent,
|
traceToParent,
|
||||||
parentNodeKey: parentFilename
|
parentNodeKey: parentFilename,
|
||||||
|
mainKeyInTrace: nodeTrace[nodeTrace.length - 1]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mainKeys[componentKey] = tempRef;
|
||||||
|
|
||||||
if (!added(property.$ref, referencesInNode)) {
|
if (!added(property.$ref, referencesInNode)) {
|
||||||
referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node });
|
referencesInNode.push({ path: pathSolver(property), keyInComponents: nodeTrace, newValue: this.node });
|
||||||
}
|
}
|
||||||
@@ -280,10 +343,11 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
|
|||||||
* @param {Array} allData - array of { path, content} objects
|
* @param {Array} allData - array of { path, content} objects
|
||||||
* @param {object} specRoot - root file information
|
* @param {object} specRoot - root file information
|
||||||
* @param {string} version - The current version
|
* @param {string} version - The current version
|
||||||
|
* @param {object} rootMainKeys - A dictionary with the component keys in local components object and its mainKeys
|
||||||
* @param {string} commonPathFromData - The common path in the file's paths
|
* @param {string} commonPathFromData - The common path in the file's paths
|
||||||
* @returns {object} - Detect root files result object
|
* @returns {object} - Detect root files result object
|
||||||
*/
|
*/
|
||||||
function getNodeContentAndReferences (currentNode, allData, specRoot, version, commonPathFromData) {
|
function getNodeContentAndReferences (currentNode, allData, specRoot, version, rootMainKeys, commonPathFromData) {
|
||||||
let graphAdj = [],
|
let graphAdj = [],
|
||||||
missingNodes = [],
|
missingNodes = [],
|
||||||
nodeContent;
|
nodeContent;
|
||||||
@@ -301,6 +365,7 @@ function getNodeContentAndReferences (currentNode, allData, specRoot, version, c
|
|||||||
removeLocalReferenceFromPath,
|
removeLocalReferenceFromPath,
|
||||||
currentNode.fileName,
|
currentNode.fileName,
|
||||||
version,
|
version,
|
||||||
|
rootMainKeys,
|
||||||
commonPathFromData
|
commonPathFromData
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -418,6 +483,25 @@ function generateComponentsWrapper(parsedOasObject) {
|
|||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a dictionary with the resusable component keys and their mainKeys in document before the bundle
|
||||||
|
* @param {object} components - The wrapper with the root reusable components before the bundle
|
||||||
|
* @param {string} version - The spec version
|
||||||
|
* @returns {object} - A directory with the local components keys related with their mainKeys
|
||||||
|
*/
|
||||||
|
function getMainKeysFromComponents(components, version) {
|
||||||
|
const {
|
||||||
|
COMPONENTS_KEYS
|
||||||
|
} = getBundleRulesDataByVersion(version);
|
||||||
|
let componentsDictionary = {};
|
||||||
|
COMPONENTS_KEYS.forEach((key) => {
|
||||||
|
if (components[key]) {
|
||||||
|
componentsDictionary[key] = Object.keys(components[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return componentsDictionary;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
/**
|
||||||
* Takes in an spec root file and an array of data files
|
* Takes in an spec root file and an array of data files
|
||||||
@@ -433,6 +517,8 @@ module.exports = {
|
|||||||
if (origin === BROWSER) {
|
if (origin === BROWSER) {
|
||||||
path = pathBrowserify;
|
path = pathBrowserify;
|
||||||
}
|
}
|
||||||
|
const initialComponents = generateComponentsWrapper(specRoot.parsed.oasObject, version),
|
||||||
|
initialMainKeys = getMainKeysFromComponents(initialComponents, version);
|
||||||
let algorithm = new DFS(),
|
let algorithm = new DFS(),
|
||||||
components = {},
|
components = {},
|
||||||
commonPathFromData = '',
|
commonPathFromData = '',
|
||||||
@@ -441,7 +527,7 @@ module.exports = {
|
|||||||
return fileData.fileName;
|
return fileData.fileName;
|
||||||
}));
|
}));
|
||||||
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => {
|
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => {
|
||||||
return getNodeContentAndReferences(currentNode, allData, specRoot, version, commonPathFromData);
|
return getNodeContentAndReferences(currentNode, allData, specRoot, version, initialMainKeys, commonPathFromData);
|
||||||
});
|
});
|
||||||
components = generateComponentsWrapper(specRoot.parsed.oasObject, version);
|
components = generateComponentsWrapper(specRoot.parsed.oasObject, version);
|
||||||
generateComponentsObject(
|
generateComponentsObject(
|
||||||
|
|||||||
@@ -22,17 +22,6 @@ function jsonPointerEncodeAndReplace(filePathName) {
|
|||||||
return encodeURIComponent(filePathName.replace(tildes, escapedTildeString).replace(slashes, escapedSlashString));
|
return encodeURIComponent(filePathName.replace(tildes, escapedTildeString).replace(slashes, escapedSlashString));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a path and return a valid key name in openapi spec
|
|
||||||
* @param {string} filePathName - The filePath from the ref called
|
|
||||||
* @returns {string} A valid in openapi object name
|
|
||||||
*/
|
|
||||||
function generateObjectName(filePathName) {
|
|
||||||
let validName = filePathName.replace(/\//g, '_').replace(/#/g, '-');
|
|
||||||
validName = validName.replace(/[^a-zA-Z0-9\.\-_]/g, '');
|
|
||||||
return validName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes a json pointer
|
* Decodes a json pointer
|
||||||
* replaces ~0 and ~1 for tildes and slashes
|
* replaces ~0 and ~1 for tildes and slashes
|
||||||
@@ -43,29 +32,41 @@ function jsonPointerDecodeAndReplace(filePathName) {
|
|||||||
return decodeURIComponent(filePathName.replace(escapedSlash, jsonPointerLevelSeparator).replace(escapedTilde, '~'));
|
return decodeURIComponent(filePathName.replace(escapedSlash, jsonPointerLevelSeparator).replace(escapedTilde, '~'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a path and return a valid key name in openapi spec
|
||||||
|
* @param {string} filePathName - The filePath from the ref called
|
||||||
|
* @param {string} hash - A calculated hash to join with the resultant generatedName
|
||||||
|
* @returns {string} A valid in openapi object name
|
||||||
|
*/
|
||||||
|
function generateObjectName(filePathName, hash = '') {
|
||||||
|
let decodedRef = jsonPointerDecodeAndReplace(filePathName),
|
||||||
|
validName = decodedRef.replace(/\//g, '_').replace(/#/g, '-'),
|
||||||
|
hashPart = hash ? `_${hash}` : '';
|
||||||
|
validName = `${validName.replace(/[^a-zA-Z0-9\.\-_]/g, '')}${hashPart}`;
|
||||||
|
return validName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the key that the object in components will have could be nested
|
* returns the key that the object in components will have could be nested
|
||||||
* @param {string} traceFromParent the node trace from root.
|
* @param {string} traceFromParent the node trace from root.
|
||||||
* @param {string} filePathName the filePathName of the file
|
* @param {string} mainKey - The generated mainKey for the components
|
||||||
* @param {string} localPath the local path that the pointer will reach
|
|
||||||
* @param {string} version - The current spec version
|
* @param {string} version - The current spec version
|
||||||
* @param {string} commonPathFromData - The common path in the file's paths
|
* @param {string} commonPathFromData - The common path in the file's paths
|
||||||
* @returns {Array} - the calculated keys in an array representing each nesting property name
|
* @returns {Array} - the calculated keys in an array representing each nesting property name
|
||||||
*/
|
*/
|
||||||
function getKeyInComponents(traceFromParent, filePathName, localPath, version, commonPathFromData) {
|
function getKeyInComponents(traceFromParent, mainKey, version, commonPathFromData) {
|
||||||
const localPart = localPath ? `${localPointer}${localPath}` : '',
|
const {
|
||||||
{
|
CONTAINERS,
|
||||||
CONTAINERS,
|
DEFINITIONS,
|
||||||
DEFINITIONS,
|
COMPONENTS_KEYS,
|
||||||
COMPONENTS_KEYS,
|
INLINE,
|
||||||
INLINE,
|
ROOT_CONTAINERS_KEYS
|
||||||
ROOT_CONTAINERS_KEYS
|
} = getBundleRulesDataByVersion(version);
|
||||||
} = getBundleRulesDataByVersion(version);
|
|
||||||
let result,
|
let result,
|
||||||
newFPN = filePathName.replace(commonPathFromData, ''),
|
newFPN = mainKey.replace(generateObjectName(commonPathFromData), ''),
|
||||||
trace = [
|
trace = [
|
||||||
...traceFromParent,
|
...traceFromParent,
|
||||||
jsonPointerDecodeAndReplace(`${newFPN}${localPart}`)
|
jsonPointerDecodeAndReplace(newFPN)
|
||||||
].reverse(),
|
].reverse(),
|
||||||
traceToKey = [],
|
traceToKey = [],
|
||||||
matchFound = false,
|
matchFound = false,
|
||||||
@@ -93,7 +94,7 @@ function getKeyInComponents(traceFromParent, filePathName, localPath, version, c
|
|||||||
result = matchFound ?
|
result = matchFound ?
|
||||||
traceToKey.reverse() :
|
traceToKey.reverse() :
|
||||||
[];
|
[];
|
||||||
return result.map(generateObjectName);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Sample API",
|
||||||
|
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
|
||||||
|
"version": "0.1.9"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://api.example.com/v1",
|
||||||
|
"description": "Optional server description, e.g. Main (production) server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://staging-api.example.com",
|
||||||
|
"description": "Optional server description, e.g. Internal staging server for testing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/users/{userId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a user by ID",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A single user.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/_schemas___user.yaml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users/weird": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a user by ID",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A single user.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/_schemas___user.yaml_RQm8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users/other": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a user by ID",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A single user.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/_schemas___user.yaml_mvS0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"_schemas___user.yaml": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"userName": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_schemas___user.yaml_RQm8": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"otherCollisionedId": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"someData": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_schemas___user.yaml_mvS0": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"aCollisionedItem": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"userName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"randomString": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: Sample API
|
||||||
|
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
|
||||||
|
version: 0.1.9
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: http://api.example.com/v1
|
||||||
|
description: Optional server description, e.g. Main (production) server
|
||||||
|
- url: http://staging-api.example.com
|
||||||
|
description: Optional server description, e.g. Internal staging server for testing
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/users/{userId}:
|
||||||
|
get:
|
||||||
|
summary: Get a user by ID
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A single user.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "./schemas__/user.yaml"
|
||||||
|
/users/weird:
|
||||||
|
get:
|
||||||
|
summary: Get a user by ID
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A single user.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "./schemas_/_user.yaml"
|
||||||
|
/users/other:
|
||||||
|
get:
|
||||||
|
summary: Get a user by ID
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A single user.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "./schemas/__user.yaml"
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
aCollisionedItem:
|
||||||
|
type: integer
|
||||||
|
userName:
|
||||||
|
type: string
|
||||||
|
randomString:
|
||||||
|
type: string
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
otherCollisionedId:
|
||||||
|
type: integer
|
||||||
|
someData:
|
||||||
|
type: string
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
userName:
|
||||||
|
type: string
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.0.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Sample API",
|
||||||
|
"description": "Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.",
|
||||||
|
"version": "0.1.9"
|
||||||
|
},
|
||||||
|
"servers": [
|
||||||
|
{
|
||||||
|
"url": "http://api.example.com/v1",
|
||||||
|
"description": "Optional server description, e.g. Main (production) server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "http://staging-api.example.com",
|
||||||
|
"description": "Optional server description, e.g. Internal staging server for testing"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/users/{userId}": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a user by ID",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A single user.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/_schemas_user.yaml_zfNS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/users/other": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get a user by ID",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A single user.",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/_schemas_user.yaml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"_schemas_user.yaml": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"componentInRootId": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"_schemas_user.yaml_zfNS": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"aCollisionedItem": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"userName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"randomString": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
openapi: 3.0.0
|
||||||
|
info:
|
||||||
|
title: Sample API
|
||||||
|
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
|
||||||
|
version: 0.1.9
|
||||||
|
|
||||||
|
servers:
|
||||||
|
- url: http://api.example.com/v1
|
||||||
|
description: Optional server description, e.g. Main (production) server
|
||||||
|
- url: http://staging-api.example.com
|
||||||
|
description: Optional server description, e.g. Internal staging server for testing
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/users/{userId}:
|
||||||
|
get:
|
||||||
|
summary: Get a user by ID
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A single user.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "./schemas/user.yaml"
|
||||||
|
/users/other:
|
||||||
|
get:
|
||||||
|
summary: Get a user by ID
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: A single user.
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/_schemas_user.yaml"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
"_schemas_user.yaml":
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
componentInRootId:
|
||||||
|
type: string
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
aCollisionedItem:
|
||||||
|
type: integer
|
||||||
|
userName:
|
||||||
|
type: string
|
||||||
|
randomString:
|
||||||
|
type: string
|
||||||
@@ -38,7 +38,9 @@ let expect = require('chai').expect,
|
|||||||
compositeOneOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_oneOf'),
|
compositeOneOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_oneOf'),
|
||||||
compositeNot = path.join(__dirname, BUNDLES_FOLDER + '/composite_not'),
|
compositeNot = path.join(__dirname, BUNDLES_FOLDER + '/composite_not'),
|
||||||
compositeAnyOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_anyOf'),
|
compositeAnyOf = path.join(__dirname, BUNDLES_FOLDER + '/composite_anyOf'),
|
||||||
longPath = path.join(__dirname, BUNDLES_FOLDER + '/longPath');
|
longPath = path.join(__dirname, BUNDLES_FOLDER + '/longPath'),
|
||||||
|
schemaCollision = path.join(__dirname, BUNDLES_FOLDER + '/schema_collision_from_responses'),
|
||||||
|
schemaCollisionWRootComponent = path.join(__dirname, BUNDLES_FOLDER + '/schema_collision_w_root_components');
|
||||||
|
|
||||||
|
|
||||||
describe('bundle files method - 3.0', function () {
|
describe('bundle files method - 3.0', function () {
|
||||||
@@ -1935,6 +1937,82 @@ describe('bundle files method - 3.0', function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Should return bundled file as json - schema_collision_from_responses', async function () {
|
||||||
|
let contentRootFile = fs.readFileSync(schemaCollision + '/root.yaml', 'utf8'),
|
||||||
|
user = fs.readFileSync(schemaCollision + '/schemas_/_user.yaml', 'utf8'),
|
||||||
|
user1 = fs.readFileSync(schemaCollision + '/schemas/__user.yaml', 'utf8'),
|
||||||
|
user2 = fs.readFileSync(schemaCollision + '/schemas__/user.yaml', 'utf8'),
|
||||||
|
expected = fs.readFileSync(schemaCollision + '/expected.json', 'utf8'),
|
||||||
|
input = {
|
||||||
|
type: 'multiFile',
|
||||||
|
specificationVersion: '3.0',
|
||||||
|
rootFiles: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml',
|
||||||
|
content: contentRootFile
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/schemas__/user.yaml',
|
||||||
|
content: user2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/schemas_/_user.yaml',
|
||||||
|
content: user
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/schemas/__user.yaml',
|
||||||
|
content: user1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
options: {},
|
||||||
|
bundleFormat: 'JSON'
|
||||||
|
};
|
||||||
|
const res = await Converter.bundle(input);
|
||||||
|
|
||||||
|
expect(res).to.not.be.empty;
|
||||||
|
expect(res.result).to.be.true;
|
||||||
|
expect(res.output.specification.version).to.equal('3.0');
|
||||||
|
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return bundled file as json - schema_collision_w_root_components', async function () {
|
||||||
|
let contentRootFile = fs.readFileSync(schemaCollisionWRootComponent + '/root.yaml', 'utf8'),
|
||||||
|
user = fs.readFileSync(schemaCollisionWRootComponent + '/schemas/user.yaml', 'utf8'),
|
||||||
|
expected = fs.readFileSync(schemaCollisionWRootComponent + '/expected.json', 'utf8'),
|
||||||
|
input = {
|
||||||
|
type: 'multiFile',
|
||||||
|
specificationVersion: '3.0',
|
||||||
|
rootFiles: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
path: '/root.yaml',
|
||||||
|
content: contentRootFile
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/schemas/user.yaml',
|
||||||
|
content: user
|
||||||
|
}
|
||||||
|
],
|
||||||
|
options: {},
|
||||||
|
bundleFormat: 'JSON'
|
||||||
|
};
|
||||||
|
const res = await Converter.bundle(input);
|
||||||
|
|
||||||
|
expect(res).to.not.be.empty;
|
||||||
|
expect(res.result).to.be.true;
|
||||||
|
expect(res.output.specification.version).to.equal('3.0');
|
||||||
|
expect(JSON.stringify(JSON.parse(res.output.data[0].bundledContent), null, 2)).to.be.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
it('Should bundle long paths into shorter ones', async function () {
|
it('Should bundle long paths into shorter ones', async function () {
|
||||||
let contentRootFile = fs.readFileSync(longPath + '/root.yaml', 'utf8'),
|
let contentRootFile = fs.readFileSync(longPath + '/root.yaml', 'utf8'),
|
||||||
client = fs.readFileSync(longPath + '/client.json', 'utf8'),
|
client = fs.readFileSync(longPath + '/client.json', 'utf8'),
|
||||||
@@ -2009,7 +2087,10 @@ describe('getReferences method when node does not have any reference', function(
|
|||||||
userNode.oasObject,
|
userNode.oasObject,
|
||||||
nodeIsRoot,
|
nodeIsRoot,
|
||||||
removeLocalReferenceFromPath,
|
removeLocalReferenceFromPath,
|
||||||
'the/parent/filename'
|
'the/parent/filename',
|
||||||
|
'3.0',
|
||||||
|
{},
|
||||||
|
''
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.referencesInNode).to.be.an('array').with.length(0);
|
expect(result.referencesInNode).to.be.an('array').with.length(0);
|
||||||
@@ -2041,7 +2122,8 @@ describe('getReferences method when node does not have any reference', function(
|
|||||||
userNode.oasObject,
|
userNode.oasObject,
|
||||||
nodeIsRoot,
|
nodeIsRoot,
|
||||||
removeLocalReferenceFromPath,
|
removeLocalReferenceFromPath,
|
||||||
'the/parent/filename'
|
'the/parent/filename',
|
||||||
|
{}
|
||||||
);
|
);
|
||||||
expect(result.nodeReferenceDirectory).to.be.an('object');
|
expect(result.nodeReferenceDirectory).to.be.an('object');
|
||||||
expect(Object.keys(result.nodeReferenceDirectory).length).to.equal(1);
|
expect(Object.keys(result.nodeReferenceDirectory).length).to.equal(1);
|
||||||
|
|||||||
@@ -18,43 +18,12 @@ describe('getKeyInComponents function', function () {
|
|||||||
expect(result).to.be.an('array').with.length(0);
|
expect(result).to.be.an('array').with.length(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return ["schemas", "_folder_pet.yaml"] when the filename scaped slash', function () {
|
it('should return ["schemas", "_folder_pet.yaml"] when the filename is _folder_pet.yaml', function () {
|
||||||
const result = getKeyInComponents(['path', 'schemas'], '~1folder~1pet.yaml');
|
const result = getKeyInComponents(['path', 'schemas'], '_folder_pet.yaml', '3.0', '');
|
||||||
expect(result).to.be.an('array').with.length(2);
|
expect(result).to.be.an('array').with.length(2);
|
||||||
expect(result[0]).to.equal('schemas');
|
expect(result[0]).to.equal('schemas');
|
||||||
expect(result[1]).to.equal('_folder_pet.yaml');
|
expect(result[1]).to.equal('_folder_pet.yaml');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return ["schemas", "_folder_pet.yaml"] when the filename contains any slash', function () {
|
|
||||||
const result = getKeyInComponents(['path', 'schemas'], '/folder/pet.yaml');
|
|
||||||
expect(result).to.be.an('array').with.length(2);
|
|
||||||
expect(result[0]).to.equal('schemas');
|
|
||||||
expect(result[1]).to.equal('_folder_pet.yaml');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return ["schemas", "_folder_pet.yaml-_Name"] when the filename contains any sacped slash' +
|
|
||||||
'and a local part using a scaped sharp', function () {
|
|
||||||
const result = getKeyInComponents(['path', 'schemas'], '~1folder~1pet.yaml%23~1Name');
|
|
||||||
expect(result).to.be.an('array').with.length(2);
|
|
||||||
expect(result[0]).to.equal('schemas');
|
|
||||||
expect(result[1]).to.equal('_folder_pet.yaml-_Name');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return ["schemas", "_folder_pet.yaml-_Name"] when the filename contains any slash' +
|
|
||||||
'and a local part using a sharp', function () {
|
|
||||||
const result = getKeyInComponents(['path', 'schemas'], '/folder/pet.yaml#/Name');
|
|
||||||
expect(result).to.be.an('array').with.length(2);
|
|
||||||
expect(result[0]).to.equal('schemas');
|
|
||||||
expect(result[1]).to.equal('_folder_pet.yaml-_Name');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return ["schemas", "_foldertest_pet.yaml-_Name"] when the filename contains any slash' +
|
|
||||||
'and a local part using a sharp and another not valid character', function () {
|
|
||||||
const result = getKeyInComponents(['path', 'schemas'], '/folder@test/pet@.yaml#/Name');
|
|
||||||
expect(result).to.be.an('array').with.length(2);
|
|
||||||
expect(result[0]).to.equal('schemas');
|
|
||||||
expect(result[1]).to.equal('_foldertest_pet.yaml-_Name');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user