swagger-parser
Advanced tools
Comparing version 1.0.4 to 1.0.5
@@ -97,3 +97,3 @@ (function() { | ||
if (_.isEmpty(pointerValue)) { | ||
util.doCallback(callback, util.syntaxError('Empty $ref pointer at "%s"', pointerPath)); | ||
return util.doCallback(callback, util.syntaxError('Empty $ref pointer at "%s"', pointerPath)); | ||
} | ||
@@ -140,10 +140,7 @@ | ||
function(err, data) { | ||
if (err || data === undefined) { | ||
err = util.syntaxError('Unable to resolve %s. An error occurred while downloading JSON data from %s : \n%s', | ||
pointerPath, pointerValue, err ? err.message : 'File Not Found'); | ||
if (!err) { | ||
// Now that we've finished downloaded the data, update the empty object we created earlier | ||
data = _.extend(state.resolvedPointers[pointerValue], data); | ||
} | ||
// Now that we've finished downloaded the data, update the empty object we created earlier | ||
data = _.extend(state.resolvedPointers[pointerValue], data); | ||
return returnResolvedValue(err, data); | ||
@@ -171,3 +168,3 @@ } | ||
function isInternalPointer(pointerValue) { | ||
return pointerValue.indexOf('#/') === 0; | ||
return pointerValue && pointerValue.indexOf('#/') === 0; | ||
} | ||
@@ -181,3 +178,3 @@ | ||
function isExternalPointer(pointerValue) { | ||
return pointerValue.indexOf('http://') === 0 || pointerValue.indexOf('https://') === 0; | ||
return pointerValue && (pointerValue.indexOf('http://') === 0 || pointerValue.indexOf('https://') === 0); | ||
} | ||
@@ -199,3 +196,5 @@ | ||
// Exit the loop early if we get a falsy value | ||
if (!obj) break; | ||
if (!obj) { | ||
break; | ||
} | ||
} | ||
@@ -202,0 +201,0 @@ |
@@ -57,8 +57,2 @@ (function() { | ||
// Make sure it's an object | ||
if (!_.isPlainObject(swaggerObject)) { | ||
state.reset(); | ||
return util.doCallback(callback, util.syntaxError('"%s" is not a valid Swagger spec', swaggerFile)); | ||
} | ||
// Validate the version number | ||
@@ -105,3 +99,5 @@ var version = swaggerObject.swagger; | ||
// Don't do anything if validation is disabled | ||
if (!state.options.validateSpec) return; | ||
if (!state.options.validateSpec) { | ||
return; | ||
} | ||
@@ -108,0 +104,0 @@ // Validate against the schema |
119
lib/read.js
@@ -22,32 +22,11 @@ (function() { | ||
try { | ||
// If we're running in the browser, then the "fs" module is unavailable, | ||
// so treat everything as a URL | ||
if (isBrowser()) { | ||
return read.url(pathOrUrl, callback); | ||
} | ||
// Parse the path and determine whether it's a file or a URL by its protocol | ||
var parsedUrl = url.parse(pathOrUrl); | ||
switch (parsedUrl.protocol) { | ||
case 'file:': | ||
case null: | ||
read.file(parsedUrl.pathname, callback); | ||
break; | ||
case 'http:': | ||
case 'https:': | ||
var relativePath = urlToRelativePath(parsedUrl); | ||
if (isLocalFile(relativePath)) { | ||
// The URL points to a local file, so bypass HTTP and read it directly | ||
read.file(relativePath, callback); | ||
} | ||
else { | ||
read.url(parsedUrl.href, callback); | ||
} | ||
break; | ||
default: | ||
callback(util.syntaxError('Unsupported file path or URL protocol "%s"', pathOrUrl)); | ||
if (isLocalFile(parsedUrl)) { | ||
read.file(urlToRelativePath(parsedUrl), callback); | ||
} | ||
else { | ||
read.url(parsedUrl.href, callback); | ||
} | ||
} | ||
@@ -67,5 +46,9 @@ catch (e) { | ||
function errorHandler(err) { | ||
callback(util.syntaxError('Unable to read file "%s": \n%s \n\n%s', filePath, err.message, err.stack)); | ||
callback(util.error('Error opening file "%s": \n%s: %s \n\n%s', filePath, err.name, err.message, err.stack)); | ||
} | ||
function parseError(err) { | ||
callback(util.syntaxError('Error parsing file "%s": \n%s: %s \n\n%s', filePath, err.name, err.message, err.stack)); | ||
} | ||
try { | ||
@@ -86,3 +69,3 @@ // Get the file path, relative to the Swagger file's directory | ||
catch (e) { | ||
errorHandler(e); | ||
parseError(e); | ||
} | ||
@@ -105,16 +88,23 @@ }); | ||
function errorHandler(err) { | ||
callback(util.syntaxError('Unable to download file "%s": \n%s \n\n%s', href, err.message, err.stack)); | ||
// NOTE: When HTTP errors occur, they can trigger multiple on('error') events, | ||
// So we need to make sure we only invoke the callback function ONCE. | ||
callback = _.once(callback); | ||
function downloadError(err) { | ||
callback(util.error('Error downloading file "%s": \n%s: %s \n\n%s', href, err.name, err.message, err.stack)); | ||
} | ||
function parseError(err) { | ||
callback(util.syntaxError('Error parsing file "%s": \n%s: %s \n\n%s', href, err.name, err.message, err.stack)); | ||
} | ||
try { | ||
// If the hostname is "." or "..", then treat it as a relative URL instead of absolute | ||
// NOTE: This is an undocumented feature that's only intended for cross-platform testing. Don't rely on it! | ||
// Parse the URL, if it's not already parsed | ||
urlPath = url.parse(urlPath); | ||
if (urlPath.host === '.' || urlPath.host === '..') { | ||
urlPath = urlToRelativePath(urlPath); | ||
if (isRelativeUrl(urlPath)) { | ||
// Resolve the url, relative to the Swagger file | ||
urlPath = url.parse(url.resolve(state.swaggerSourceDir + '/', urlToRelativePath(urlPath))); | ||
} | ||
// Resolve the url, relative to the Swagger file | ||
urlPath = url.parse(url.resolve(state.swaggerSourceDir + '/', urlPath)); | ||
href = urlPath.href; | ||
@@ -146,3 +136,3 @@ | ||
if (res.statusCode >= 400) { | ||
return errorHandler(new Error(body)); | ||
return downloadError(new Error('HTTP ERROR ' + res.statusCode + ': ' + body)); | ||
} | ||
@@ -154,3 +144,3 @@ | ||
catch (e) { | ||
errorHandler(e); | ||
parseError(e); | ||
} | ||
@@ -160,3 +150,3 @@ }); | ||
res.on('error', function(e) { | ||
errorHandler(e); | ||
downloadError(e); | ||
}); | ||
@@ -174,7 +164,7 @@ }); | ||
req.on('error', function(e) { | ||
errorHandler(e); | ||
downloadError(e); | ||
}); | ||
} | ||
catch (e) { | ||
errorHandler(e); | ||
downloadError(e); | ||
} | ||
@@ -195,6 +185,32 @@ } | ||
/** | ||
* Determines whether the given path points to a local file that exists. | ||
* @param {Url} parsedUrl A parsed Url object | ||
* @returns {boolean} | ||
*/ | ||
function isLocalFile(parsedUrl) { | ||
if (isBrowser()) { | ||
// Local files aren't supported in browsers | ||
return false; | ||
} | ||
if (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') { | ||
// If the path exists locally, then treat the URL as a local file | ||
var relativePath = urlToRelativePath(parsedUrl); | ||
var filePath = path.resolve(state.swaggerSourceDir, relativePath); | ||
return fs.existsSync(filePath); | ||
} | ||
// If it's anything other than "http" or "https", then assume it's a local file. | ||
// This includes "file://", "/absolute/paths", "relative/paths", and "c:\windows\paths" | ||
return true; | ||
} | ||
/** | ||
* Return the equivalent relative file path for a given url. | ||
* @param {Url} parsedUrl A parsed Url object | ||
* @returns {string} | ||
*/ | ||
function urlToRelativePath(parsedUrl) { | ||
if (parsedUrl.host === '.' || parsedUrl.host === '..') { | ||
if (isRelativeUrl(parsedUrl)) { | ||
// "http://../../file.yaml" => "../../file.yaml" | ||
@@ -210,9 +226,9 @@ return parsedUrl.href.substr(parsedUrl.protocol.length + 2); | ||
/** | ||
* Determines whether the given path points to a local file that exists. | ||
* Treats a URL as relative if its hostname is "." or ".." | ||
* NOTE: This is an undocumented feature that's only intended for cross-platform testing. Don't rely on it! | ||
* @param {Url} parsedUrl A parsed Url object | ||
* @returns {boolean} | ||
*/ | ||
function isLocalFile(filePath) { | ||
// Resolve the path, relative to the Swagger file | ||
filePath = path.resolve(state.swaggerSourceDir, filePath); | ||
return fs.existsSync(filePath); | ||
function isRelativeUrl(parsedUrl) { | ||
return parsedUrl.host === '.' || parsedUrl.host === '..'; | ||
} | ||
@@ -238,3 +254,10 @@ | ||
debug(' Parsed successfully'); | ||
if (_.isEmpty(parsedObject)) { | ||
throw util.syntaxError('Parsed value is empty'); | ||
} | ||
if (!_.isPlainObject(parsedObject)) { | ||
throw util.syntaxError('Parsed value is not a valid JavaScript object'); | ||
} | ||
debug(' Parsed successfully'); | ||
return parsedObject; | ||
@@ -241,0 +264,0 @@ } |
@@ -26,2 +26,13 @@ (function() { | ||
/** | ||
* Creates an Error with a formatted string message. | ||
* @param {string} message | ||
* @param {...*} [params] | ||
* @returns {Error} | ||
*/ | ||
error: function(message, params) { | ||
return new Error(format.apply(null, [message].concat(_.rest(arguments)))); | ||
}, | ||
/** | ||
* Creates a SyntaxError with a formatted string message. | ||
@@ -28,0 +39,0 @@ * @param {string} message |
{ | ||
"name": "swagger-parser", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "Parses a JSON or YAML Swagger spec, validates it against the Swagger schema, and dereferences all $ref pointers", | ||
@@ -25,3 +25,3 @@ "keywords": [ | ||
"build": "gulp build", | ||
"test": "mocha --ui bdd --recursive tests && karma start --single-run" | ||
"test": "istanbul cover _mocha -- --recursive tests && karma start --single-run" | ||
}, | ||
@@ -36,3 +36,3 @@ "repository": { | ||
"lodash": "^2.4.1", | ||
"swagger-schema-official": "^2.0.0-a33091a", | ||
"swagger-schema-official": "2.0.0-a33091a", | ||
"tv4": "^1.1.0" | ||
@@ -43,2 +43,3 @@ }, | ||
"chai": "^1.10.0", | ||
"coveralls": "^2.11.2", | ||
"gulp": "^3.8.10", | ||
@@ -48,2 +49,3 @@ "gulp-rename": "^1.2.0", | ||
"gulp-uglify": "^1.0.1", | ||
"istanbul": "^0.3.5", | ||
"jquery": "^2.1.1", | ||
@@ -62,2 +64,3 @@ "karma": "^0.12.28", | ||
"mocha": "^2.0.1", | ||
"nock": "^0.51.0", | ||
"sinon": "^1.12.1", | ||
@@ -64,0 +67,0 @@ "vinyl-buffer": "^1.0.0", |
@@ -7,2 +7,8 @@ Swagger-Parser | ||
[![Dependencies](https://david-dm.org/bigstickcarpet/swagger-parser.svg)](https://david-dm.org/bigstickcarpet/swagger-parser) | ||
[![Code Climate Score](https://codeclimate.com/github/BigstickCarpet/swagger-parser/badges/gpa.svg)](https://codeclimate.com/github/BigstickCarpet/swagger-parser) | ||
[![Codacy Score](http://img.shields.io/codacy/6d686f916836433b9c013379fbe1052c.svg)](https://www.codacy.com/public/jamesmessinger/swagger-parser) | ||
[![Coverage Status](https://img.shields.io/coveralls/BigstickCarpet/swagger-parser.svg)](https://coveralls.io/r/BigstickCarpet/swagger-parser) | ||
[![npm](http://img.shields.io/npm/v/swagger-parser.svg)](#node) | ||
[![Bower](http://img.shields.io/bower/v/swagger-parser.svg)](#bower) | ||
[![License](https://img.shields.io/npm/l/swagger-parser.svg)](LICENSE) | ||
@@ -13,3 +19,3 @@ | ||
* Supports Swagger specs in __JSON or YAML__ format | ||
* Validates against the [official Swagger 2.0 schema](http://github.com/reverb/swagger-spec/blob/master/versions/2.0.md) | ||
* __Validates__ against the [official Swagger 2.0 schema](http://github.com/reverb/swagger-spec/blob/master/versions/2.0.md) | ||
* Dereferences all __$ref__ pointers, including pointers to external URLs | ||
@@ -16,0 +22,0 @@ * Nested $ref pointers are supported, even in external URLs |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
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
2957346
121
25
16
23760
+ Addedswagger-schema-official@2.0.0-a33091a(transitive)
- Removedswagger-schema-official@2.0.0-d79c205(transitive)