Fixing value key to resolve inline

This commit is contained in:
Erik Mendoza
2022-07-06 15:53:07 -05:00
parent 73d7aaca4d
commit f0a7ad3daf
10 changed files with 897 additions and 72 deletions

View File

@@ -289,10 +289,11 @@ function handleLocalCollisions(trace, initialMainKeys) {
* @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 {Array} allData - array of { path, content} objects
* @param {object} globalReferences - The accumulated global references from all nodes
* @returns {object} - The references in current node and the new content from the node
*/
function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, version, rootMainKeys,
commonPathFromData, allData) {
commonPathFromData, allData, globalReferences) {
let referencesInNode = [],
nodeReferenceDirectory = {},
mainKeys = {};
@@ -350,17 +351,19 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
inline = true;
}
nodeReferenceDirectory[tempRef] = {
local,
keyInComponents: nodeTrace,
node: newValue,
reference: inline ? newRefInDoc : referenceInDocument,
traceToParent,
parentNodeKey: parentFilename,
mainKeyInTrace: nodeTrace[nodeTrace.length - 1],
refHasContent,
inline
};
if (_.isNil(globalReferences[tempRef])) {
nodeReferenceDirectory[tempRef] = {
local,
keyInComponents: nodeTrace,
node: newValue,
reference: inline ? newRefInDoc : referenceInDocument,
traceToParent,
parentNodeKey: parentFilename,
mainKeyInTrace: nodeTrace[nodeTrace.length - 1],
refHasContent,
inline
};
}
mainKeys[componentKey] = tempRef;
@@ -382,9 +385,11 @@ function getReferences (currentNode, isOutOfRoot, pathSolver, parentFilename, ve
* @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 {object} globalReferences - The accumulated global refernces from all nodes
* @returns {object} - Detect root files result object
*/
function getNodeContentAndReferences (currentNode, allData, specRoot, version, rootMainKeys, commonPathFromData) {
function getNodeContentAndReferences (currentNode, allData, specRoot, version, rootMainKeys,
commonPathFromData, globalReferences) {
let graphAdj = [],
missingNodes = [],
nodeContent,
@@ -409,7 +414,8 @@ function getNodeContentAndReferences (currentNode, allData, specRoot, version, r
version,
rootMainKeys,
commonPathFromData,
allData
allData,
globalReferences
);
referencesInNode.forEach((reference) => {
@@ -632,8 +638,16 @@ module.exports = {
commonPathFromData = Utils.findCommonSubpath(allData.map((fileData) => {
return fileData.fileName;
}));
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode) => {
return getNodeContentAndReferences(currentNode, allData, specRoot, version, initialMainKeys, commonPathFromData);
rootContextData = algorithm.traverseAndBundle(specRoot, (currentNode, globalReferences) => {
return getNodeContentAndReferences(
currentNode,
allData,
specRoot,
version,
initialMainKeys,
commonPathFromData,
globalReferences
);
});
components = generateComponentsWrapper(
specRoot.parsed.oasObject,

View File

@@ -8,8 +8,7 @@ const SCHEMA_CONTAINERS = [
'schema'
],
EXAMPLE_CONTAINERS = [
'example',
'value'
'example'
],
REQUEST_BODY_CONTAINER = [
'requestBody'
@@ -26,7 +25,10 @@ const SCHEMA_CONTAINERS = [
properties: 'schemas',
links: 'links'
},
INLINE = ['properties'],
INLINE = [
'properties',
'value'
],
ROOT_CONTAINERS_KEYS = [
'components'
],

View File

@@ -8,8 +8,7 @@ const SCHEMA_CONTAINERS = [
'schema'
],
EXAMPLE_CONTAINERS = [
'example',
'value'
'example'
],
REQUEST_BODY_CONTAINER = [
'requestBody'
@@ -27,7 +26,10 @@ const SCHEMA_CONTAINERS = [
links: 'links',
paths: 'pathItems'
},
INLINE = ['properties'],
INLINE = [
'properties',
'value'
],
ROOT_CONTAINERS_KEYS = [
'components'
],

View File

@@ -48,7 +48,7 @@ class DFS {
nodeContent,
nodeReferenceDirectory,
nodeName
} = getAdjacentAndBundle(node);
} = getAdjacentAndBundle(node, globalReferences);
nodeContents[nodeName] = nodeContent;
Object.entries(nodeReferenceDirectory).forEach(([key, data]) => {
globalReferences[key] = data;

View File

@@ -0,0 +1,15 @@
{
"considerIp": "false",
"wifiAccessPoints": [
{
"macAddress": "84:d4:7e:09:a5:f1",
"signalStrength": -43,
"signalToNoiseRatio": 0
},
{
"macAddress": "44:48:c1:a6:f3:d0",
"signalStrength": -55,
"signalToNoiseRatio": 0
}
]
}

View File

@@ -0,0 +1,466 @@
{
"openapi": "3.0.0",
"info": {
"version": "1.0.10",
"title": "Petstore 224",
"description": "A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification",
"termsOfService": "http://swagger.io/terms/",
"contact": {
"name": "Postman"
},
"license": {
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
"x-postman-projectname": "PostmanPetstore"
},
"paths": {
"/pets": {
"parameters": [
{
"name": "GlobalParam",
"in": "query",
"schema": {
"type": "string"
}
},
{
"name": "GlobalCookie",
"in": "cookie",
"schema": {
"type": "string"
}
}
],
"post": {
"description": "Creates a new pet in the store. Duplicates are allowed",
"operationId": "addPet",
"requestBody": {
"description": "Pet to add to the store",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"responses": {
"201": {
"description": "Pet was created successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
},
"examples": {
"WIFI": {
"value": {
"considerIp": "false",
"wifiAccessPoints": [
{
"macAddress": "84:d4:7e:09:a5:f1",
"signalStrength": -43,
"signalToNoiseRatio": 0
},
{
"macAddress": "44:48:c1:a6:f3:d0",
"signalStrength": -55,
"signalToNoiseRatio": 0
}
]
}
}
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/pets/{id}": {
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of pet to work with in operations",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"get": {
"description": "Returns a user based on a single ID, if the user does not have access to the pet",
"operationId": "find pet by id",
"responses": {
"200": {
"description": "pet response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"description": "Replaces Pet with contents",
"operationId": "replacePet",
"requestBody": {
"description": "Pet to replace with",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"responses": {
"200": {
"description": "Pet updated correctly",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"description": "Updates Pet with contents",
"operationId": "UPDATEPET",
"requestBody": {
"description": "Pet to update with",
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"responses": {
"200": {
"description": "Pet updated correctly",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/stores": {
"get": {
"description": "Retrieves contents of stores",
"operationId": "GetAllStores",
"responses": {
"200": {
"description": "Returns list of Store items",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"typeOf": {
"type": "string",
"enum": [
"Cat",
"Dog",
"Bird",
"Reptile"
]
},
"tag": {
"type": "string"
},
"value": {
"type": "number",
"format": "float",
"description": "price"
},
"saleValue": {
"type": "number",
"format": "float",
"description": "price if on sale"
},
"onSale": {
"type": "boolean",
"default": false,
"description": "True if item is on sale, false if not."
}
}
}
}
}
}
},
"400": {
"description": "No items found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Something went wrong on server",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/stores/{id}": {
"get": {
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of store to fetch",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "pet response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/StoreItem"
}
}
}
},
"default": {
"description": "unexpected error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/stores/{id}/pets": {
"get": {
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of store to fetch",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"description": "Retrieves contents of stores",
"operationId": "GetAllPetsForStoreById",
"responses": {
"200": {
"description": "Returns list of Store items",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pets"
}
}
}
},
"400": {
"description": "No items found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"description": "Something went wrong on server",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"description": "A pet",
"required": [
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"typeOf": {
"type": "string",
"enum": [
"Cat",
"Dog",
"Bird",
"Reptile"
]
},
"tag": {
"type": "string"
}
}
},
"Pets": {
"type": "object",
"properties": {
"id": {
"type": "integer"
}
}
},
"StoreItem": {
"description": "Single store item",
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"typeOf": {
"type": "string",
"enum": [
"Cat",
"Dog",
"Bird",
"Reptile"
]
},
"tag": {
"type": "string"
},
"value": {
"type": "number",
"format": "float",
"description": "price"
},
"saleValue": {
"type": "number",
"format": "float",
"description": "price if on sale"
},
"onSale": {
"type": "boolean",
"default": false,
"description": "True if item is on sale, false if not."
}
}
},
"Error": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"message": {
"type": "string"
}
}
}
}
}
}

View File

@@ -0,0 +1,286 @@
openapi: "3.0.0"
info:
version: 1.0.10
title: Petstore 224
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification
termsOfService: http://swagger.io/terms/
contact:
name: Postman
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
x-postman-projectname: PostmanPetstore
paths:
/pets:
parameters:
- name: GlobalParam
in: query
schema:
type: string
- name: GlobalCookie
in: cookie
schema:
type: string
post:
description: Creates a new pet in the store. Duplicates are allowed
operationId: addPet
requestBody:
description: Pet to add to the store
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
201:
description: Pet was created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
examples:
WIFI:
value:
$ref: "./example.yml"
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pets/{id}:
parameters:
- name: id
in: path
description: ID of pet to work with in operations
required: true
schema:
type: integer
format: int64
get:
description: Returns a user based on a single ID, if the user does not have access to the pet
operationId: find pet by id
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
description: Replaces Pet with contents
operationId: replacePet
requestBody:
description: Pet to replace with
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
200:
description: Pet updated correctly
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
patch:
description: Updates Pet with contents
operationId: UPDATEPET
requestBody:
description: Pet to update with
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
'200':
description: Pet updated correctly
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/stores:
get:
description: Retrieves contents of stores
operationId: GetAllStores
responses:
200:
description: Returns list of Store items
content:
application/json:
schema:
type: array
items:
properties:
id:
type: integer
format: int64
name:
type: string
typeOf:
type: string
enum: [Cat, Dog, Bird, Reptile]
tag:
type: string
value:
type: number
format: float
description: price
saleValue:
type: number
format: float
description: price if on sale
onSale:
type: boolean
default: false
description: True if item is on sale, false if not.
400:
description: No items found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
500:
description: Something went wrong on server
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/stores/{id}:
get:
parameters:
- name: id
in: path
description: ID of store to fetch
required: true
schema:
type: integer
format: int64
responses:
'200':
description: pet response
content:
application/json:
schema:
$ref: '#/components/schemas/StoreItem'
default:
description: unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/stores/{id}/pets:
get:
parameters:
- name: id
in: path
description: ID of store to fetch
required: true
schema:
type: integer
format: int64
description: Retrieves contents of stores
operationId: GetAllPetsForStoreById
responses:
200:
description: Returns list of Store items
content:
application/json:
schema:
$ref: '#/components/schemas/Pets'
400:
description: No items found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
500:
description: Something went wrong on server
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Pet:
type: object
description: A pet
required:
- name
properties:
id:
type: integer
format: int64
name:
type: string
typeOf:
type: string
enum: [Cat, Dog, Bird, Reptile]
tag:
type: string
Pets:
type: object
properties:
id:
type: integer
StoreItem:
description: Single store item
properties:
id:
type: integer
format: int64
name:
type: string
typeOf:
type: string
enum: [ Cat, Dog, Bird, Reptile ]
tag:
type: string
value:
type: number
format: float
description: price
saleValue:
type: number
format: float
description: price if on sale
onSale:
type: boolean
default: false
description: True if item is on sale, false if not.
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string

View File

@@ -33,7 +33,11 @@
"examples": {
"WIFI": {
"value": {
"$ref": "#/components/examples/_responses_maps_http_geolocation_wifi_response.yml"
"location": {
"lat": 37.421925,
"lng": -122.0841293
},
"accuracy": 30
}
}
}
@@ -69,7 +73,34 @@
"examples": {
"WIFI": {
"value": {
"$ref": "#/components/examples/_requests_maps_http_geolocation_wifi_request.yml"
"considerIp": "false",
"wifiAccessPoints": [
{
"macAddress": "84:d4:7e:09:a5:f1",
"signalStrength": -43,
"signalToNoiseRatio": 0
},
{
"macAddress": "44:48:c1:a6:f3:d0",
"signalStrength": -55,
"signalToNoiseRatio": 0
}
]
}
},
"Cell Towers": {
"value": {
"cellTowers": [
{
"cellId": 170402199,
"locationAreaCode": 35632,
"mobileCountryCode": 310,
"mobileNetworkCode": 410,
"age": 0,
"signalStrength": -60,
"timingAdvance": 15
}
]
}
}
}
@@ -121,7 +152,6 @@
],
"properties": {
"location": {
"description": "The users estimated latitude and longitude, in degrees.",
"$ref": "#/components/schemas/_schemas_LatLngLiteral.yml"
},
"accuracy": {
@@ -130,7 +160,11 @@
}
},
"example": {
"$ref": "#/components/examples/_responses_maps_http_geolocation_wifi_response.yml"
"location": {
"lat": 37.421925,
"lng": -122.0841293
},
"accuracy": 30
}
},
"_schemas_test.yml": {
@@ -219,7 +253,17 @@
}
},
"example": {
"$ref": "#/components/examples/_requests_maps_http_geolocation_celltowers_request.yml"
"cellTowers": [
{
"cellId": 170402199,
"locationAreaCode": 35632,
"mobileCountryCode": 310,
"mobileNetworkCode": 410,
"age": 0,
"signalStrength": -60,
"timingAdvance": 15
}
]
}
},
"Bounds": {
@@ -232,11 +276,9 @@
],
"properties": {
"northeast": {
"description": "The users estimated latitude and longitude, in degrees.",
"$ref": "#/components/schemas/_schemas_LatLngLiteral.yml"
},
"southwest": {
"description": "The users estimated latitude and longitude, in degrees.",
"$ref": "#/components/schemas/_schemas_LatLngLiteral.yml"
}
}
@@ -248,43 +290,6 @@
"in": "query",
"name": "key"
}
},
"examples": {
"_responses_maps_http_geolocation_wifi_response.yml": {
"location": {
"lat": 37.421925,
"lng": -122.0841293
},
"accuracy": 30
},
"_requests_maps_http_geolocation_wifi_request.yml": {
"considerIp": "false",
"wifiAccessPoints": [
{
"macAddress": "84:d4:7e:09:a5:f1",
"signalStrength": -43,
"signalToNoiseRatio": 0
},
{
"macAddress": "44:48:c1:a6:f3:d0",
"signalStrength": -55,
"signalToNoiseRatio": 0
}
]
},
"_requests_maps_http_geolocation_celltowers_request.yml": {
"cellTowers": [
{
"cellId": 170402199,
"locationAreaCode": 35632,
"mobileCountryCode": 310,
"mobileNetworkCode": 410,
"age": 0,
"signalStrength": -60,
"timingAdvance": 15
}
]
}
}
},
"security": [

View File

@@ -71,9 +71,9 @@ requestBody:
WIFI:
value:
$ref: ../requests/maps_http_geolocation_wifi_request.yml
# Cell Towers:
# value:
# $ref: ../requests/maps_http_geolocation_celltowers_request.yml
Cell Towers:
value:
$ref: ../requests/maps_http_geolocation_celltowers_request.yml
# IP Only:
# value:
# $ref: ../requests/maps_http_geolocation_ip_request.yml

View File

@@ -45,7 +45,8 @@ let expect = require('chai').expect,
nestedExamplesAsValue = path.join(__dirname, BUNDLES_FOLDER + '/nested_examples_as_value'),
referencedComponents = path.join(__dirname, BUNDLES_FOLDER + '/referenced_components'),
referencedPath = path.join(__dirname, BUNDLES_FOLDER + '/referenced_path'),
referencedPathSchema = path.join(__dirname, BUNDLES_FOLDER + '/paths_schema');
referencedPathSchema = path.join(__dirname, BUNDLES_FOLDER + '/paths_schema'),
exampleValue = path.join(__dirname, BUNDLES_FOLDER + '/example_value');
describe('bundle files method - 3.0', function () {
it('Should return bundled file as json - schema_from_response', async function () {
@@ -2555,6 +2556,39 @@ describe('bundle files method - 3.0', function () {
expect(res.result).to.be.true;
expect(res.output.data[0].referenceMap).to.deep.equal(expectedMap);
});
it('Should return bundled file - example_schema', async function () {
let contentRootFile = fs.readFileSync(exampleValue + '/root.yml', 'utf8'),
example = fs.readFileSync(exampleValue + '/example.yml', 'utf8'),
expected = fs.readFileSync(exampleValue + '/expected.json', 'utf8'),
input = {
type: 'multiFile',
specificationVersion: '3.0',
rootFiles: [
{
path: '/root.yml'
}
],
data: [
{
path: '/root.yml',
content: contentRootFile
},
{
path: '/example.yml',
content: example
}
],
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);
});
});
describe('getReferences method when node does not have any reference', function() {
@@ -2611,7 +2645,8 @@ describe('getReferences method when node does not have any reference', function(
'3.0',
{},
'',
[]
[],
{}
);
expect(result.nodeReferenceDirectory).to.be.an('object');
expect(Object.keys(result.nodeReferenceDirectory).length).to.equal(1);