From fa623d32c0898258fe62cb6ef60603038ac284a9 Mon Sep 17 00:00:00 2001 From: Erik Mendoza Date: Thu, 28 Apr 2022 16:38:18 -0500 Subject: [PATCH] Fix swagger to openapi convertion Removing async await implementation and using callback implementation instead. Fixin the related tests --- lib/schemapack.js | 204 +++++++++++++-------------- lib/swaggerUtils/swaggerToOpenapi.js | 20 ++- test/unit/swaggerToOpenapi.test.js | 21 ++- 3 files changed, 123 insertions(+), 122 deletions(-) diff --git a/lib/schemapack.js b/lib/schemapack.js index a4345a7..f713e10 100644 --- a/lib/schemapack.js +++ b/lib/schemapack.js @@ -1,10 +1,9 @@ 'use strict'; -const { convertSwaggerToOpenapi } = require('./swaggerUtils/swaggerToOpenapi.js'); - // This is the default collection name if one can't be inferred from the OpenAPI spec const COLLECTION_NAME = 'Imported from OpenAPI 3.0', - { getConcreteSchemaUtils, isSwagger } = require('./common/versionUtils.js'), + { getConcreteSchemaUtils } = require('./common/versionUtils.js'), + { convertSwaggerToOpenapi } = require('./swaggerUtils/swaggerToOpenapi.js'), BROWSER = 'browser', Ajv = require('ajv'), addFormats = require('ajv-formats'), @@ -239,7 +238,7 @@ class SchemaPack { // convert method, this is called when you want to convert a schema that you've already loaded // in the constructor - async convert (callback) { + convert (callback) { let openapi, options = this.computedOptions, analysis, @@ -256,122 +255,119 @@ class SchemaPack { return callback(new OpenApiErr('The schema must be validated before attempting conversion')); } - if (isSwagger(concreteUtils.version)) { - try { - let result = await convertSwaggerToOpenapi(this.openapi); - this.openapi = result.openapi; - } - catch (error) { + convertSwaggerToOpenapi(concreteUtils, this.openapi, (error, newOpenapi) => { + if (error) { return callback(error); } - } - // this cannot be attempted before validation - specComponentsAndUtils = { concreteUtils }; - Object.assign(specComponentsAndUtils, concreteUtils.getRequiredData(this.openapi)); + this.openapi = newOpenapi; + // this cannot be attempted before validation + specComponentsAndUtils = { concreteUtils }; + Object.assign(specComponentsAndUtils, concreteUtils.getRequiredData(this.openapi)); - // create and sanitize basic spec - openapi = this.openapi; - openapi.servers = _.isEmpty(openapi.servers) ? [{ url: '/' }] : openapi.servers; - openapi.securityDefs = _.get(openapi, 'components.securitySchemes', {}); - openapi.baseUrl = _.get(openapi, 'servers.0.url', '{{baseURL}}'); + // create and sanitize basic spec + openapi = this.openapi; + openapi.servers = _.isEmpty(openapi.servers) ? [{ url: '/' }] : openapi.servers; + openapi.securityDefs = _.get(openapi, 'components.securitySchemes', {}); + openapi.baseUrl = _.get(openapi, 'servers.0.url', '{{baseURL}}'); - // TODO: Multiple server variables need to be saved as environments - openapi.baseUrlVariables = _.get(openapi, 'servers.0.variables'); + // TODO: Multiple server variables need to be saved as environments + openapi.baseUrlVariables = _.get(openapi, 'servers.0.variables'); - // Fix {scheme} and {path} vars in the URL to :scheme and :path - openapi.baseUrl = schemaUtils.fixPathVariablesInUrl(openapi.baseUrl); + // Fix {scheme} and {path} vars in the URL to :scheme and :path + openapi.baseUrl = schemaUtils.fixPathVariablesInUrl(openapi.baseUrl); - // Creating a new instance of a Postman collection - // All generated folders and requests will go inside this - generatedStore.collection = new sdk.Collection({ - info: { - name: _.isEmpty(_.get(openapi, 'info.title')) ? COLLECTION_NAME : _.get(openapi, 'info.title') + // Creating a new instance of a Postman collection + // All generated folders and requests will go inside this + generatedStore.collection = new sdk.Collection({ + info: { + name: _.isEmpty(_.get(openapi, 'info.title')) ? COLLECTION_NAME : _.get(openapi, 'info.title') + } + }); + + if (openapi.security) { + authHelper = schemaUtils.getAuthHelper(openapi, openapi.security); + if (authHelper) { + generatedStore.collection.auth = authHelper; + } } - }); + // ---- Collection Variables ---- + // adding the collection variables for all the necessary root level variables + // and adding them to the collection variables + schemaUtils.convertToPmCollectionVariables( + openapi.baseUrlVariables, + 'baseUrl', + openapi.baseUrl + ).forEach((element) => { + generatedStore.collection.variables.add(element); + }); - if (openapi.security) { - authHelper = schemaUtils.getAuthHelper(openapi, openapi.security); - if (authHelper) { - generatedStore.collection.auth = authHelper; - } - } - // ---- Collection Variables ---- - // adding the collection variables for all the necessary root level variables - // and adding them to the collection variables - schemaUtils.convertToPmCollectionVariables( - openapi.baseUrlVariables, - 'baseUrl', - openapi.baseUrl - ).forEach((element) => { - generatedStore.collection.variables.add(element); - }); + generatedStore.collection.describe(schemaUtils.getCollectionDescription(openapi)); - generatedStore.collection.describe(schemaUtils.getCollectionDescription(openapi)); + // Only change the stack limit if the optimizeConversion option is true + if (options.optimizeConversion) { + // Deciding stack limit based on size of the schema, number of refs and number of paths. + analysis = schemaUtils.analyzeSpec(openapi); - // Only change the stack limit if the optimizeConversion option is true - if (options.optimizeConversion) { - // Deciding stack limit based on size of the schema, number of refs and number of paths. - analysis = schemaUtils.analyzeSpec(openapi); - - // Update options on the basis of analysis. - options = schemaUtils.determineOptions(analysis, options); - } - - - // ---- Collection Items ---- - // Adding the collection items from openapi spec based on folderStrategy option - // For tags, All operations are grouped based on respective tags object - // For paths, All operations are grouped based on corresponding paths - try { - if (options.folderStrategy === 'tags') { - schemaUtils.addCollectionItemsUsingTags( - openapi, - generatedStore, - specComponentsAndUtils, - options, - schemaCache, - concreteUtils - ); - } - else { - schemaUtils.addCollectionItemsUsingPaths( - openapi, - generatedStore, - specComponentsAndUtils, - options, - schemaCache, - concreteUtils - ); + // Update options on the basis of analysis. + options = schemaUtils.determineOptions(analysis, options); } - if (options.includeWebhooks) { - schemaUtils.addCollectionItemsFromWebhooks( - openapi, - generatedStore, - specComponentsAndUtils, - options, - schemaCache, - concreteUtils - ); + + // ---- Collection Items ---- + // Adding the collection items from openapi spec based on folderStrategy option + // For tags, All operations are grouped based on respective tags object + // For paths, All operations are grouped based on corresponding paths + try { + if (options.folderStrategy === 'tags') { + schemaUtils.addCollectionItemsUsingTags( + openapi, + generatedStore, + specComponentsAndUtils, + options, + schemaCache, + concreteUtils + ); + } + else { + schemaUtils.addCollectionItemsUsingPaths( + openapi, + generatedStore, + specComponentsAndUtils, + options, + schemaCache, + concreteUtils + ); + } + + if (options.includeWebhooks) { + schemaUtils.addCollectionItemsFromWebhooks( + openapi, + generatedStore, + specComponentsAndUtils, + options, + schemaCache, + concreteUtils + ); + } + } + catch (e) { + return callback(e); } - } - catch (e) { - return callback(e); - } - collectionJSON = generatedStore.collection.toJSON(); + collectionJSON = generatedStore.collection.toJSON(); - // this needs to be deleted as even if version is not specified to sdk, - // it returns a version property with value set as undefined - // this fails validation against v2.1 collection schema definition. - delete collectionJSON.info.version; + // this needs to be deleted as even if version is not specified to sdk, + // it returns a version property with value set as undefined + // this fails validation against v2.1 collection schema definition. + delete collectionJSON.info.version; - return callback(null, { - result: true, - output: [{ - type: 'collection', - data: collectionJSON - }] + return callback(null, { + result: true, + output: [{ + type: 'collection', + data: collectionJSON + }] + }); }); } diff --git a/lib/swaggerUtils/swaggerToOpenapi.js b/lib/swaggerUtils/swaggerToOpenapi.js index 584050a..601b72b 100644 --- a/lib/swaggerUtils/swaggerToOpenapi.js +++ b/lib/swaggerUtils/swaggerToOpenapi.js @@ -1,21 +1,27 @@ -const Swagger2OpenAPI = require('swagger2openapi'); +const Swagger2OpenAPI = require('swagger2openapi'), + { isSwagger } = require('../common/versionUtils'); module.exports = { - convertSwaggerToOpenapi: function(parsedSwagger) { - try { - return Swagger2OpenAPI.convertObj( + convertSwaggerToOpenapi: function(concreteUtils, parsedSwagger, convertExecution) { + if (isSwagger(concreteUtils.version)) { + Swagger2OpenAPI.convertObj( parsedSwagger, { fatal: false, patch: true, anchors: true, warnOnly: true + }, + (error, newOpenapi) => { + if (error) { + return convertExecution(error); + } + return convertExecution(null, newOpenapi.openapi); } ); } - catch (error) { - throw error; + else { + return convertExecution(null, parsedSwagger); } - } }; diff --git a/test/unit/swaggerToOpenapi.test.js b/test/unit/swaggerToOpenapi.test.js index 027cf75..fad1a76 100644 --- a/test/unit/swaggerToOpenapi.test.js +++ b/test/unit/swaggerToOpenapi.test.js @@ -6,25 +6,24 @@ const { convertSwaggerToOpenapi } = require('../../lib/swaggerUtils/swaggerToOpe utils = require('../../lib/swaggerUtils/schemaUtilsSwagger'), expect = require('chai').expect; -describe('Test swaggerToOpenapi method', async function() { - it('Should convert a swagger file to an openapi', async function() { +describe('Test swaggerToOpenapi method', function() { + it('Should convert a swagger file to an openapi', function() { const fileSource = path.join(__dirname, SWAGGER_20_FOLDER_JSON + '/sampleswagger.json'), fileData = fs.readFileSync(fileSource, 'utf8'), parsedSpec = utils.parseSpec(fileData); - let result = await convertSwaggerToOpenapi(parsedSpec.openapi); - expect(result.openapi.openapi).to.be.equal('3.0.0'); + convertSwaggerToOpenapi(utils, parsedSpec.openapi, (error, openapi) => { + expect(error).to.be.null; + expect(openapi.openapi).to.be.equal('3.0.0'); + }); }); - it('Should throw an error when swagger file is not complete', async function() { + it('Should throw an error when swagger file is not complete', function() { const fileSource = path.join(__dirname, SWAGGER_20_INVALID_FOLDER_JSON + '/invalid_no_info.json'), fileData = fs.readFileSync(fileSource, 'utf8'), parsedSpec = utils.parseSpec(fileData); - try { - await convertSwaggerToOpenapi(parsedSpec.openapi); - expect.fail(); - } - catch (error) { + convertSwaggerToOpenapi(utils, parsedSpec.openapi, (error, openapi) => { expect(error.message).to.be.equal('Unsupported swagger/OpenAPI version: undefined'); - } + expect(openapi).to.be.undefined; + }); }); });