swagger-tools
Advanced tools
Comparing version 0.7.0 to 0.7.1
@@ -86,2 +86,18 @@ /* | ||
module.exports.getErrorCount = function getErrorCount (results) { | ||
var errors = 0; | ||
if (results) { | ||
errors = results.errors.length; | ||
_.each(results.apiDeclarations, function (adResults) { | ||
if (adResults) { | ||
errors += adResults.errors.length; | ||
} | ||
}); | ||
} | ||
return errors; | ||
}; | ||
/** | ||
@@ -145,4 +161,6 @@ * Returns the proper specification based on the human readable version. | ||
var printErrorsOrWarnings = function printErrorsOrWarnings (header, entries, indent) { | ||
console.error(header); | ||
console.error(); | ||
if (header) { | ||
console.error(header + ':'); | ||
console.error(); | ||
} | ||
@@ -153,7 +171,9 @@ _.each(entries, function (entry) { | ||
if (entry.inner) { | ||
printErrorsOrWarnings (header, entry.inner, indent + 2); | ||
printErrorsOrWarnings (undefined, entry.inner, indent + 2); | ||
} | ||
}); | ||
console.error(); | ||
if (header) { | ||
console.error(); | ||
} | ||
}; | ||
@@ -168,3 +188,3 @@ var errorCount = 0; | ||
printErrorsOrWarnings('API Errors:', results.errors, 2); | ||
printErrorsOrWarnings('API Errors', results.errors, 2); | ||
} | ||
@@ -175,3 +195,3 @@ | ||
printErrorsOrWarnings('API Warnings:', results.warnings, 2); | ||
printErrorsOrWarnings('API Warnings', results.warnings, 2); | ||
} | ||
@@ -190,3 +210,3 @@ | ||
printErrorsOrWarnings(' API Declaration (' + name + ') Errors:', adResult.errors, 4); | ||
printErrorsOrWarnings(' API Declaration (' + name + ') Errors', adResult.errors, 4); | ||
} | ||
@@ -197,3 +217,3 @@ | ||
printErrorsOrWarnings(' API Declaration (' + name + ') Warnings:', adResult.warnings, 4); | ||
printErrorsOrWarnings(' API Declaration (' + name + ') Warnings', adResult.warnings, 4); | ||
} | ||
@@ -200,0 +220,0 @@ }); |
@@ -32,2 +32,3 @@ /* | ||
var SparkMD5 = require('spark-md5'); | ||
var swaggerConverter = require('swagger-converter'); | ||
var traverse = require('traverse'); | ||
@@ -229,7 +230,12 @@ var validators = require('./validators'); | ||
var handleValidationError = function handleValidationError (results, callback) { | ||
var err = new Error('The Swagger document is invalid and model composition is not possible'); | ||
var err = new Error('The Swagger document(s) are invalid'); | ||
err.errors = results.errors; | ||
err.failedValidation = true; | ||
err.warnings = results.warnings; | ||
if (results.apiDeclarations) { | ||
err.apiDeclarations = results.apiDeclarations; | ||
} | ||
callback(err); | ||
@@ -1158,3 +1164,3 @@ }; | ||
return callback(err); | ||
} else if (helpers.formatResults(results)) { | ||
} else if (helpers.getErrorCount(results) > 0) { | ||
return handleValidationError(results, callback); | ||
@@ -1175,3 +1181,3 @@ } | ||
if (helpers.formatResults(results)) { | ||
if (helpers.getErrorCount(results) > 0) { | ||
return handleValidationError(results, callback); | ||
@@ -1364,3 +1370,3 @@ } | ||
return callback(err); | ||
} else if (helpers.formatResults(results)) { | ||
} else if (helpers.getErrorCount(results) > 0) { | ||
return handleValidationError(results, callback); | ||
@@ -1376,3 +1382,65 @@ } | ||
/** | ||
* Converts the Swagger 1.2 documents to a Swagger 2.0 document. | ||
* | ||
* @param {object} resourceListing - The Swagger Resource Listing | ||
* @param {object[]} [apiDeclarations] - The array of Swagger API Declarations | ||
* @param {boolean=false} [skipValidation] - Whether or not to skip validation | ||
* @param {resultCallback} callback - The result callback | ||
* | ||
* @returns the converted Swagger document | ||
* | ||
* @throws Error if the arguments provided are not valid | ||
*/ | ||
Specification.prototype.convert = function (resourceListing, apiDeclarations, skipValidation, callback) { | ||
var doConvert = function doConvert (resourceListing, apiDeclarations) { | ||
callback(undefined, swaggerConverter(resourceListing, apiDeclarations)); | ||
}.bind(this); | ||
if (this.version !== '1.2') { | ||
throw new Error('Specification#convert only works for Swagger 1.2'); | ||
} | ||
// Validate arguments | ||
if (_.isUndefined(resourceListing)) { | ||
throw new Error('resourceListing is required'); | ||
} else if (!_.isPlainObject(resourceListing)) { | ||
throw new TypeError('resourceListing must be an object'); | ||
} | ||
// API Declarations are optional because swagger-converter was written to support it | ||
if (_.isUndefined(apiDeclarations)) { | ||
apiDeclarations = []; | ||
} | ||
if (!_.isArray(apiDeclarations)) { | ||
throw new TypeError('apiDeclarations must be an array'); | ||
} | ||
if (arguments.length < 4) { | ||
callback = arguments[arguments.length - 1]; | ||
} | ||
if (_.isUndefined(callback)) { | ||
throw new Error('callback is required'); | ||
} else if (!_.isFunction(callback)) { | ||
throw new TypeError('callback must be a function'); | ||
} | ||
if (skipValidation === true) { | ||
doConvert(resourceListing, apiDeclarations); | ||
} else { | ||
this.validate(resourceListing, apiDeclarations, function (err, results) { | ||
if (err) { | ||
return callback(err); | ||
} else if (helpers.getErrorCount(results) > 0) { | ||
return handleValidationError(results, callback); | ||
} | ||
doConvert(resourceListing, apiDeclarations); | ||
}); | ||
} | ||
}; | ||
module.exports.v1 = module.exports.v1_2 = new Specification('1.2'); // jshint ignore:line | ||
module.exports.v2 = module.exports.v2_0 = new Specification('2.0'); // jshint ignore:line |
@@ -160,21 +160,31 @@ /* | ||
/** | ||
* Validates the request's content type (when necessary). | ||
* Validates the request or response content type (when necessary). | ||
* | ||
* @param {string[]} gConsumes - The valid consumes at the API scope | ||
* @param {string[]} oConsumes - The valid consumes at the operation scope | ||
* @param {object} req - The request | ||
* @param {string[]} gPOrC - The valid consumes at the API scope | ||
* @param {string[]} oPOrC - The valid consumes at the operation scope | ||
* @param {object} reqOrRes - The request or response | ||
* | ||
* @throws Error if the content type is invalid | ||
*/ | ||
module.exports.validateContentType = function validateContentType (gConsumes, oConsumes, req) { | ||
module.exports.validateContentType = function validateContentType (gPOrC, oPOrC, reqOrRes) { | ||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 | ||
var contentType = req.headers['content-type'] || 'application/octet-stream'; | ||
var consumes = _.union(oConsumes, gConsumes); | ||
var isResponse = typeof reqOrRes.end === 'function'; | ||
var contentType = isResponse ? reqOrRes.getHeader('content-type') : reqOrRes.headers['content-type']; | ||
var pOrC = _.union(gPOrC, oPOrC); | ||
if (!contentType) { | ||
if (isResponse) { | ||
contentType = 'text/plain'; | ||
} else { | ||
contentType = 'application/octet-stream'; | ||
} | ||
} | ||
// Get only the content type | ||
contentType = contentType.split(';')[0]; | ||
// Validate content type (Only for POST/PUT per HTTP spec) | ||
if (consumes.length > 0 && ['POST', 'PUT'].indexOf(req.method) !== -1 && consumes.indexOf(contentType) === -1) { | ||
throw new Error('Invalid content type (' + contentType + '). These are valid: ' + consumes.join(', ')); | ||
if (pOrC.length > 0 && (isResponse ? | ||
true : | ||
['POST', 'PUT'].indexOf(reqOrRes.method) !== -1) && pOrC.indexOf(contentType) === -1) { | ||
throw new Error('Invalid content type (' + contentType + '). These are valid: ' + pOrC.join(', ')); | ||
} | ||
@@ -443,2 +453,5 @@ }; | ||
break; | ||
case 'void': | ||
result = _.isUndefined(val); | ||
break; | ||
} | ||
@@ -451,3 +464,5 @@ } | ||
throwErrorWithCode('INVALID_TYPE', | ||
'Not a valid ' + (_.isUndefined(format) ? '' : format + ' ') + type + ': ' + val); | ||
type !== 'void' ? | ||
'Not a valid ' + (_.isUndefined(format) ? '' : format + ' ') + type + ': ' + val : | ||
'Void does not allow a value'); | ||
} | ||
@@ -492,9 +507,16 @@ }; | ||
}; | ||
var type = schema.type; | ||
// Resolve the actual schema object | ||
schema = resolveSchema(schema); | ||
if (!type) { | ||
if (!schema.schema) { | ||
type = 'void'; | ||
} else { | ||
schema = resolveSchema(schema); | ||
type = schema.type || 'object'; | ||
} | ||
} | ||
try { | ||
// Always perform this check even if there is no value | ||
if (schema.type === 'array') { | ||
if (type === 'array') { | ||
validateArrayType(schema); | ||
@@ -515,13 +537,13 @@ } | ||
if (schema.type === 'array') { | ||
if (type === 'array') { | ||
if (!_.isUndefined(schema.items)) { | ||
validateTypeAndFormat(val, schema.type === 'array' ? schema.items.type : schema.type, | ||
schema.type === 'array' && schema.items.format ? | ||
validateTypeAndFormat(val, type === 'array' ? schema.items.type : type, | ||
type === 'array' && schema.items.format ? | ||
schema.items.format : | ||
schema.format); | ||
} else { | ||
validateTypeAndFormat(val, schema.type, schema.format); | ||
validateTypeAndFormat(val, type, schema.format); | ||
} | ||
} else { | ||
validateTypeAndFormat(val, schema.type, schema.format); | ||
validateTypeAndFormat(val, type, schema.format); | ||
} | ||
@@ -533,3 +555,3 @@ | ||
// Validate maximum | ||
validateMaximum(val, schema.maximum, schema.type, schema.exclusiveMaximum); | ||
validateMaximum(val, schema.maximum, type, schema.exclusiveMaximum); | ||
@@ -547,3 +569,3 @@ | ||
// Validate minimum | ||
validateMinimum(val, schema.minimum, schema.type, schema.exclusiveMinimum); | ||
validateMinimum(val, schema.minimum, type, schema.exclusiveMinimum); | ||
@@ -550,0 +572,0 @@ // Validate minItems |
@@ -31,7 +31,6 @@ /* | ||
var send400 = helpers.send400; | ||
var spec = require('../../lib/helpers').getSpec('1.2'); | ||
var validators = require('../../lib/validators'); | ||
/** | ||
* Middleware for using Swagger information to validate API requests prior to sending the request to the route handler. | ||
* Middleware for using Swagger information to validate API requests/responses. | ||
* | ||
@@ -41,5 +40,12 @@ * This middleware also requires that you use the swagger-metadata middleware before this middleware. This middleware | ||
* | ||
* @param {object} [options] - The middleware options | ||
* @param {boolean} [options.validateResponse=false] - Whether or not to validate responses | ||
* | ||
* @returns the middleware function | ||
*/ | ||
exports = module.exports = function swaggerValidatorMiddleware () { | ||
exports = module.exports = function swaggerValidatorMiddleware (options) { | ||
if (_.isUndefined(options)) { | ||
options = {}; | ||
} | ||
return function swaggerValidator (req, res, next) { | ||
@@ -53,2 +59,7 @@ var operation = req.swagger ? req.swagger.operation : undefined; | ||
// If necessary, override 'res.send' | ||
if (options.validateResponse === true) { | ||
helpers.wrapEnd('1.2', req, res, next); | ||
} | ||
// Validate the request | ||
@@ -60,3 +71,2 @@ try { | ||
async.map(operation.parameters, function (parameter, oCallback) { | ||
var isModel = helpers.isModelParameter('1.2', parameter); | ||
var val; | ||
@@ -76,32 +86,4 @@ | ||
validators.validateSchemaConstraints('1.2', parameter, paramPath, val); | ||
helpers.validateValue(req, parameter, paramPath, val, oCallback); | ||
if (isModel) { | ||
async.map(parameter.type === 'array' ? val : [val], function (aVal, callback) { | ||
spec.validateModel(req.swagger.apiDeclaration, | ||
'#/models/' + (parameter.items ? | ||
parameter.items.type || parameter.items.$ref : | ||
parameter.type), | ||
aVal, callback); | ||
}, function (err, allResults) { | ||
if (!err) { | ||
_.each(allResults, function (results) { | ||
if (results) { | ||
err = new Error('Failed schema validation'); | ||
err.code = 'SCHEMA_VALIDATION_FAILED'; | ||
err.errors = results.errors; | ||
err.failedValidation = true; | ||
return false; | ||
} | ||
}); | ||
} | ||
oCallback(err); | ||
}); | ||
} else { | ||
oCallback(); | ||
} | ||
paramIndex++; | ||
@@ -108,0 +90,0 @@ }, function (err) { |
@@ -129,2 +129,3 @@ /* | ||
return function swaggerMetadata (req, res, next) { | ||
var method = req.method.toLowerCase(); | ||
var path = parseurl(req).pathname; | ||
@@ -149,5 +150,6 @@ var match; | ||
if (_.isPlainObject(pathMetadata.operations[req.method.toLowerCase()])) { | ||
metadata.operation = pathMetadata.operations[req.method.toLowerCase()].operation; | ||
metadata.operationParameters = pathMetadata.operations[req.method.toLowerCase()].parameters || []; | ||
if (_.isPlainObject(pathMetadata.operations[method])) { | ||
metadata.operation = pathMetadata.operations[method].operation; | ||
metadata.operationParameters = pathMetadata.operations[method].parameters || []; | ||
metadata.operationPath = ['paths', pathMetadata.apiPath, method]; | ||
metadata.security = metadata.operation.security || metadata.swaggerObject.security || []; | ||
@@ -154,0 +156,0 @@ } |
@@ -34,3 +34,3 @@ /* | ||
/** | ||
* Middleware for using Swagger information to validate API requests prior to sending the request to the route handler. | ||
* Middleware for using Swagger information to validate API requests/responses. | ||
* | ||
@@ -40,5 +40,12 @@ * This middleware also requires that you use the swagger-metadata middleware before this middleware. This middleware | ||
* | ||
* @param {object} [options] - The middleware options | ||
* @param {boolean} [options.validateResponse=false] - Whether or not to validate responses | ||
* | ||
* @returns the middleware function | ||
*/ | ||
exports = module.exports = function swaggerValidatorMiddleware () { | ||
exports = module.exports = function swaggerValidatorMiddleware (options) { | ||
if (_.isUndefined(options)) { | ||
options = {}; | ||
} | ||
return function swaggerValidator (req, res, next) { | ||
@@ -51,2 +58,7 @@ var operation = req.swagger ? req.swagger.operation : undefined; | ||
// If necessary, override 'res.send' | ||
if (options.validateResponse === true) { | ||
helpers.wrapEnd('2.0', req, res, next); | ||
} | ||
// Validate the request | ||
@@ -59,3 +71,2 @@ try { | ||
var parameter = paramMetadata.schema; | ||
var isModel = helpers.isModelParameter('2.0', parameter); | ||
var val; | ||
@@ -75,19 +86,3 @@ | ||
validators.validateSchemaConstraints('2.0', parameter, paramPath, val); | ||
if (isModel) { | ||
async.map(parameter.type === 'array' ? val : [val], function (aVal, callback) { | ||
try { | ||
validators.validateAgainstSchema(parameter.schema, val); | ||
} catch (err) { | ||
return callback(err); | ||
} | ||
return callback(); | ||
}, function (err) { | ||
oCallback(err); | ||
}); | ||
} else { | ||
oCallback(); | ||
} | ||
helpers.validateValue(req, parameter, paramPath, val, oCallback); | ||
}, function (err) { | ||
@@ -94,0 +89,0 @@ if (err) { |
@@ -28,7 +28,9 @@ /* | ||
var _ = require('lodash'); | ||
var async = require('async'); | ||
var fs = require('fs'); | ||
var helpers = require('../lib/helpers'); | ||
var parseurl = require('parseurl'); | ||
var path = require('path'); | ||
var validators = require('../lib/validators'); | ||
var helpers = require('../lib/helpers'); | ||
var operationVerbs = [ | ||
@@ -48,2 +50,33 @@ 'DELETE', | ||
var isModelParameter = module.exports.isModelParameter = function isModelParameter (version, param) { | ||
var spec = helpers.getSpec(version); | ||
var isModel = false; | ||
switch (version) { | ||
case '1.2': | ||
if (!_.isUndefined(param.type) && isModelType(spec, param.type)) { | ||
isModel = true; | ||
} else if (param.type === 'array' && isModelType(spec, param.items ? | ||
param.items.type || param.items.$ref : | ||
undefined)) { | ||
isModel = true; | ||
} | ||
break; | ||
case '2.0': | ||
if (param.type === 'object' || !param.type) { | ||
isModel = true; | ||
} else if (!_.isUndefined(param.schema) && (param.schema.type === 'object' || !_.isUndefined(param.schema.$ref))) { | ||
isModel = true; | ||
} | ||
// 2.0 does not allow arrays of models in the same way Swagger 1.2 does | ||
break; | ||
} | ||
return isModel; | ||
}; | ||
/** | ||
@@ -315,33 +348,2 @@ * Returns an Express style path for the Swagger path. | ||
var isModelParameter = module.exports.isModelParameter = function isModelParameter (version, param) { | ||
var spec = helpers.getSpec(version); | ||
var isModel = false; | ||
switch (version) { | ||
case '1.2': | ||
if (!_.isUndefined(spec, param.type) && isModelType(spec, param.type)) { | ||
isModel = true; | ||
} else if (param.type === 'array' && isModelType(spec, param.items ? | ||
param.items.type || param.items.$ref : | ||
undefined)) { | ||
isModel = true; | ||
} | ||
break; | ||
case '2.0': | ||
if (param.type === 'object' || !param.type) { | ||
isModel = true; | ||
} else if (!_.isUndefined(param.schema) && (param.schema.type === 'object' || !_.isUndefined(param.schema.$ref))) { | ||
isModel = true; | ||
} | ||
// 2.0 does not allow arrays of models in the same way Swagger 1.2 does | ||
break; | ||
} | ||
return isModel; | ||
}; | ||
module.exports.getParameterValue = function getParameterValue (version, parameter, pathKeys, match, req) { | ||
@@ -356,2 +358,3 @@ var defaultVal = version === '1.2' ? parameter.defaultValue : parameter.default; | ||
case 'form': | ||
case 'formData': | ||
if (!req.body) { | ||
@@ -473,1 +476,143 @@ throw new Error('Server configuration error: req.body is not defined but is required'); | ||
}; | ||
var validateValue = module.exports.validateValue = | ||
function validateValue (req, schema, path, val, callback) { | ||
var document = req.swagger.apiDeclaration || req.swagger.swaggerObject; | ||
var version = req.swagger.apiDeclaration ? '1.2' : '2.0'; | ||
var isModel = isModelParameter(version, schema); | ||
var spec = helpers.getSpec(version); | ||
try { | ||
validators.validateSchemaConstraints(version, schema, path, val); | ||
} catch (err) { | ||
return callback(err); | ||
} | ||
if (isModel) { | ||
if (_.isString(val)) { | ||
try { | ||
val = JSON.parse(val); | ||
} catch (err) { | ||
err.failedValidation = true; | ||
err.message = 'Value expected to be an array/object but is not'; | ||
throw err; | ||
} | ||
} | ||
async.map(schema.type === 'array' ? val : [val], function (aVal, oCallback) { | ||
if (version === '1.2') { | ||
spec.validateModel(document, '#/models/' + (schema.items ? | ||
schema.items.type || schema.items.$ref : | ||
schema.type), aVal, oCallback); | ||
} else { | ||
try { | ||
validators.validateAgainstSchema(schema.schema ? schema.schema : schema, val); | ||
oCallback(); | ||
} catch (err) { | ||
oCallback(err); | ||
} | ||
} | ||
}, function (err, allResults) { | ||
if (!err) { | ||
_.each(allResults, function (results) { | ||
if (results && helpers.getErrorCount(results) > 0) { | ||
err = new Error('Failed schema validation'); | ||
err.code = 'SCHEMA_VALIDATION_FAILED'; | ||
err.errors = results.errors; | ||
err.warnings = results.warnings; | ||
err.failedValidation = true; | ||
return false; | ||
} | ||
}); | ||
} | ||
callback(err); | ||
}); | ||
} else { | ||
callback(); | ||
} | ||
}; | ||
module.exports.wrapEnd = function wrapEnd (version, req, res, next) { | ||
var operation = req.swagger.operation; | ||
var originalEnd = res.end; | ||
var vPath = _.cloneDeep(req.swagger.operationPath); | ||
res.end = function end (data, encoding) { | ||
var schema = operation; | ||
var val = data; | ||
// Replace 'res.end' with the original | ||
res.end = originalEnd; | ||
// If the data is a buffer, convert it to a string so we can parse it prior to validation | ||
if (val instanceof Buffer) { | ||
val = data.toString(encoding); | ||
} | ||
try { | ||
// Validate the content type | ||
try { | ||
validators.validateContentType(req.swagger.apiDeclaration ? | ||
req.swagger.apiDeclaration.produces : | ||
req.swagger.swaggerObject.produces, | ||
operation.produces, res); | ||
} catch (err) { | ||
err.failedValidation = true; | ||
throw err; | ||
} | ||
if (_.isUndefined(schema.type)) { | ||
if (schema.schema) { | ||
schema = schema.schema; | ||
} else if (version === '1.2') { | ||
schema = _.find(operation.responseMessages, function (responseMessage, index) { | ||
if (responseMessage.code === res.statusCode) { | ||
vPath.push(['responseMessages', index.toString()]); | ||
return true; | ||
} | ||
}); | ||
if (!_.isUndefined(schema)) { | ||
schema = schema.responseModel; | ||
} | ||
} else { | ||
schema = _.find(operation.responses, function (response, code) { | ||
if (code === res.statusCode.toString()) { | ||
vPath.push(['responses', code]); | ||
return true; | ||
} | ||
}); | ||
} | ||
} | ||
validateValue(req, schema, vPath, val, | ||
function (err) { | ||
if (err) { | ||
throw err; | ||
} | ||
// 'res.end' requires a Buffer or String so if it's not one, create a String | ||
if (!(data instanceof Buffer) && !_.isString(data)) { | ||
data = JSON.stringify(data); | ||
} | ||
res.end(data, encoding); | ||
}); | ||
} catch (err) { | ||
if (err.failedValidation) { | ||
err.message = 'Response validation failed: ' + err.message.charAt(0).toLowerCase() + err.message.substring(1); | ||
} | ||
return next(err); | ||
} | ||
}; | ||
}; |
{ | ||
"name": "swagger-tools", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"description": "Various tools for using and integrating with Swagger.", | ||
@@ -67,2 +67,3 @@ "main": "index.js", | ||
"superagent": "^0.21.0", | ||
"swagger-converter": "0.0.5", | ||
"traverse": "^0.6.6", | ||
@@ -69,0 +70,0 @@ "yamljs": "^0.2.1", |
@@ -22,3 +22,5 @@ The project provides various tools for integrating and interacting with Swagger. This project is in its infancy but | ||
* Simple CLI for validating Swagger documents | ||
* Simple CLI | ||
* Validate Swagger document(s) | ||
* Convert Swagger 1.2 documents to Swagger 2.0 | ||
* Schema validation: For the file(s) supported by the Swagger specification, ensure they pass structural validation | ||
@@ -32,5 +34,6 @@ based on the [JSON Schema][json-schema] associated with that version of the specification _(Browser and Node)_ | ||
* Connect middleware for using Swagger resource documents for pre-route validation _(Node only)_ | ||
* Validate the request Content-Type based on the operation's `consumes` value(s) | ||
* Validate the request/response Content-Type based on the operation's `consumes/produces` value(s) | ||
* Validate the request parameter types | ||
* Validate the request parameter values | ||
* Validate the response values | ||
@@ -37,0 +40,0 @@ ## Installation |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
851685
17231
66
14
+ Addedswagger-converter@0.0.5
+ Addedswagger-converter@0.0.5(transitive)