Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

swagger2openapi

Package Overview
Dependencies
Maintainers
1
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

swagger2openapi - npm Package Compare versions

Comparing version 1.1.0 to 1.1.1

202

index.js
'use strict';
var crypto = require('crypto');
var jptr = require('jgexml/jpath.js');
// TODO split out into common, params, security etc
function clone(obj) {

@@ -11,2 +17,14 @@ return JSON.parse(JSON.stringify(obj));

function sha1(s) {
var shasum = crypto.createHash('sha1');
shasum.update(s);
return shasum.digest('hex');
}
String.prototype.toCamelCase = function camelize() {
return this.toLowerCase().replace(/[-_ \/\.](.)/g, function(match, group1) {
return group1.toUpperCase();
});
}
function deleteParameters(value, index, self) {

@@ -30,2 +48,9 @@ return !value["x-s2o-delete"];

function processSecurityScheme(scheme) {
if (scheme.type == 'oauth2') {
if (scheme.flow == 'application') scheme.flow = 'clientCredentials';
if (scheme.flow == 'accessCode') scheme.flow = 'authorizationCode';
}
}
function processParameter(param,op,path,index,openapi) {

@@ -38,34 +63,21 @@ var result = {};

var ptr = param["$ref"].replace('#/components/parameters/','');
var rbody = false;
var target = openapi.components.parameters[ptr];
if ((!target) || (target["x-s2o-delete"])) {
// it's gone, chances are it's a requestBody now unless spec was broken
// OR external ref - not supported yet
param["x-s2o-delete"] = true;
rbody = true;
}
// shared formData parameters could be used in any combination. We could sort and
// hash them into unique combinations, or alternatively lump them all into one bucket
// and ensure they're not required:true if they shouldn't be TODO
// shared formData parameters from swagger or path level could be used in any combination.
// probably best is to make all op.requestBody's unique then hash them and pull out
// any common ones afterwards // TODO
if (op) {
if (!op.requestBodies) op.requestBodies = {};
if (ptr) {
op.requestBodies[ptr] = {};
op.requestBodies[ptr]["$ref"] = '#/components/requestBodies/'+ptr;
}
else {
forceFailure(openapi,'Have lost a shared parameter now requestBody');
}
if (rbody) {
param = jptr.jptr(openapi,param["$ref"]);
}
else if (path) {
if (!path.requestBodies) path.requestBodies = {};
if (ptr) {
path.requestBodies[ptr] = {};
path.requestBodies[ptr]["$ref"] = '#/components/requestBodies/'+ptr;
}
else {
forceFailure(openapi,'Have lost a shared parameter now requestBody');
}
}
}
else {
if (param.type || param.in) { // if it's a real parameter OR we've dereferenced it
if (param.schema) {

@@ -84,2 +96,6 @@ recurse(param.schema,{},function(obj,key,parent){

}
if (key == 'x-not') {
obj.not = obj[key];
delete obj[key];
}
});

@@ -101,3 +117,3 @@ }

if (param.in == 'formData') {
// convert to requestBody
// convert to requestBody component
singularRequestBody = false;

@@ -115,4 +131,22 @@ result.content = {};

target.type = param.type;
if (param.format) target.format = param.format;
// TODO min/max/exclusive/minItems etc etc
target.required = param.required;
target.default = param.default;
target.format = param.format;
target.minimum = param.minimum;
target.maximum = param.maximum;
target.exclusiveMinimum = param.exclusiveMinimum;
target.exclusiveMaximum = param.exclusiveMaximum;
target.minItems = param.minItems;
target.maxItems = param.maxItems;
target.uniqueItems = param.uniqueItems;
target.pattern = param.pattern;
target.enum = param.enum;
target.multipleOf = param.multipleOf;
target.minLength = param.minLength;
target.maxLength = param.maxLength;
target.properties = param.properties;
target.minProperties = param.minProperties;
target.maxProperties = param.maxProperties;
target.additionalProperties = param.additionalProperties;
target.allOf = param.allOf; // new are anyOf, oneOf, not
if ((param.type == 'array') && (param.items)) {

@@ -136,2 +170,6 @@ target.items = param.items;

if (consumes.length == 0) {
consumes.push('application/json'); // default as per section xxx
}
for (var mimetype of consumes) {

@@ -142,7 +180,6 @@ result.content[mimetype] = {};

}
//if (consumes.length>1) {
// forceFailure(openapi,'Body mimetype may not be correct. '+consumes.length);
//}
}
// TODO multipart/formData etc
if (Object.keys(result).length > 0) {

@@ -169,16 +206,19 @@ param["x-s2o-delete"] = true;

else if (path) {
if (path.requestBody && singularRequestBody) {
path.requestBody["x-s2o-overloaded"] = true;
forceFailure(openapi,'Path has >1 requestBodies');
var uniqueName = index ? index.toCamelCase()+'RequestBodyBase' : param.name;
if (!index) {
forceFailure(openapi,'Named requestBody needs name');
}
else {
path.requestBody = Object.assign({},op.requestBody,result);
if (param.in == 'formData') {
result["x-s2o-partial"] = true;
}
openapi.components.requestBodies[uniqueName] = result;
}
else {
var uniqueName = index;
var uniqueName = index ? index : param.name;
if (!index) {
forceFailure(openapi,'Named requestBody needs name');
uniqueName = param.name;
}
if (param.in == 'formData') {
result["x-s2o-partial"] = true;
}
openapi.components.requestBodies[uniqueName] = result;

@@ -192,2 +232,4 @@ }

function convert(swagger, options) {
var requestBodyCache = {};
var openapi = {};

@@ -209,3 +251,2 @@ openapi.openapi = '3.0.0-RC0'; // semver

server.url = server.url.split('}}').join('}');
// TODO if we have non-standard path variables here expand them using a regex
openapi.servers.push(server);

@@ -229,3 +270,3 @@ }

openapi.components.requestBodies = {};
openapi.components.securitySchemes = openapi.securityDefinitions;
openapi.components.securitySchemes = openapi.securityDefinitions||{};
openapi.components.headers = {};

@@ -238,2 +279,6 @@ delete openapi.definitions;

for (var s in openapi.components.securitySchemes) {
processSecurityScheme(openapi.components.securitySchemes[s]);
}
for (var p in openapi.components.parameters) {

@@ -243,2 +288,12 @@ var param = openapi.components.parameters[p];

}
for (var r in openapi.components.requestBodies) { // converted ones
var rb = openapi.components.requestBodies[r];
var rbStr = JSON.stringify(rb);
var rbSha1 = sha1(rbStr);
var entry = {};
entry.name = r;
entry.body = rb;
entry.refs = [];
requestBodyCache[rbSha1] = entry;
}

@@ -266,6 +321,3 @@ for (var p in openapi.paths) {

// remove requestBody for non-supported ops? SHALL be ignored
//if (op.requestBody && method != 'put' && method != 'post') {
// forceFailure(openapi,'requestBody on get style operation');
//}
//don't need to remove requestBody for non-supported ops "SHALL be ignored"

@@ -278,3 +330,3 @@ // responses

if ((key == '$ref') && (typeof obj[key] === 'string')) {
obj[key] = obj[key].replace('#/definitions/','#/components/schemas');
obj[key] = obj[key].replace('#/definitions/','#/components/schemas/');
}

@@ -297,12 +349,30 @@ if (key == 'x-anyOf') {

// examples
if (options.debug) {
op["x-s2o-consumes"] = op.consumes;
op["x-s2o-produces"] = op.produces;
}
delete op.consumes;
delete op.produces;
// file types
// TODO examples
if (op.requestBody) {
var rbStr = JSON.stringify(op.requestBody);
var rbSha1 = sha1(rbStr);
if (!requestBodyCache[rbSha1]) {
var entry = {};
entry.name = '';
entry.body = op.requestBody;
entry.refs = [];
requestBodyCache[rbSha1] = entry;
}
requestBodyCache[rbSha1].refs.push(method+' '+p);
}
}
}
if (path.parameters) {
for (var p in path.parameters) {
var param = path.parameters[p];
processParameter(param,null,path,null,openapi);
for (var p2 in path.parameters) {
var param = path.parameters[p2];
processParameter(param,null,path,p,openapi); // index here is the path string
}

@@ -316,7 +386,14 @@ if (!options.debug) {

// security changes (oAuth)
if (!options.debug) {
for (var p in openapi.components.parameters) {
param = openapi.components.parameters[p];
if (param["x-s2o-delete"]) {
delete openapi.components.parameters[p];
}
}
}
recurse(openapi.components.schemas,{},function(obj,key,parent){
if ((key == '$ref') && (typeof obj[key] === 'string')) {
obj[key] = obj[key].replace('#/definitions/','#/components/schemas');
obj[key] = obj[key].replace('#/definitions/','#/components/schemas/');
}

@@ -333,7 +410,28 @@ if (key == 'x-anyOf') {

if (options.debug) openapi["x-s2o-consumes"] = openapi.consumes;
if (options.debug) {
openapi["x-s2o-consumes"] = openapi.consumes;
openapi["x-s2o-produces"] = openapi.produces;
}
delete openapi.consumes;
if (options.debug) openapi["x-s2o-produces"] = openapi.produces;
delete openapi.produces;
openapi.components.requestBodies = {}; // for now as we've dereffed them
var counter = 0;
for (var e in requestBodyCache) {
var entry = requestBodyCache[e];
if (entry.refs.length>1) {
if (!entry.name) {
entry.name = 'requestBody'+counter++;
}
// we can reinstate
openapi.components.requestBodies[entry.name] = entry.body;
for (var r in entry.refs) {
var address = entry.refs[r].split(' ');
var ref = {};
ref["$ref"] = '#/components/requestBodies/'+entry.name;
openapi.paths[address[1]][address[0]].requestBody = ref;
}
}
}
return openapi;

@@ -340,0 +438,0 @@ }

{
"name": "swagger2openapi",
"version": "1.1.0",
"version": "1.1.1",
"description": "Convert Swagger 2.0 specifications to OpenApi 3.0",
"main": "index.js",
"bin": {
"swagger2openapi": "./swagger2openapi.js"
},
"repository": {

@@ -14,5 +17,7 @@ "url": "https://github.com/Mermade/swagger2openapi.git",

"ajv": "^4.11.3",
"jgexml": "^0.3.6",
"js-yaml": "^3.6.1",
"recursive-readdir": "^2.1.1",
"yargs": "^6.2.0"
}
}

@@ -23,3 +23,4 @@ # swagger2openapi

var options = {};
//options.debug = true; // sets various x-s2o- properties for debugging
var openapi = converter.convert(swagger, options);
````

@@ -0,1 +1,3 @@

#!/usr/bin/env node
'use strict';

@@ -2,0 +4,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc