swagger-client
Advanced tools
Comparing version 2.1.7-M2 to 2.1.7
@@ -43,1 +43,2 @@ 'use strict'; | ||
SwaggerClient.SwaggerClient = deprecationWrapper; | ||
SwaggerClient.SchemaMarkup = require('./lib/schema-markup'); |
'use strict'; | ||
var helpers = require('./helpers'); | ||
var btoa = require('btoa'); // jshint ignore:line | ||
var CookieJar = require('cookiejar'); | ||
var CookieJar = require('cookiejar').CookieJar; | ||
var _ = { | ||
@@ -25,3 +26,3 @@ each: require('lodash-compat/collection/each'), | ||
SwaggerAuthorizations.prototype.add = function (name, auth) { | ||
if(name && typeof name === 'object') { | ||
if(_.isObject(name)) { | ||
for (var key in name) { | ||
@@ -42,4 +43,3 @@ this.authz[key] = name[key]; | ||
SwaggerAuthorizations.prototype.apply = function (obj, securities) { | ||
var status = null; | ||
var key, name, value, result; | ||
var status = true; | ||
var applyAll = !securities; | ||
@@ -49,3 +49,3 @@ var flattenedSecurities = []; | ||
// Securities could be [ {} ] | ||
_.each(securities, function (obj,key) { | ||
_.each(securities, function (obj, key) { | ||
@@ -65,3 +65,4 @@ // Make sure we account for securities being [ str ] | ||
if(applyAll || _.includes(flattenedSecurities, authName)) { | ||
status = status || !!auth.apply(obj); // logical ORs regarding status | ||
var newStatus = auth.apply(obj); | ||
status = status && !!newStatus; // logical ORs regarding status | ||
} | ||
@@ -84,3 +85,22 @@ }); | ||
if (this.type === 'query') { | ||
// see if already applied. If so, don't do it again | ||
var qp; | ||
if (obj.url.indexOf('?') > 0) { | ||
qp = obj.url.substring(obj.url.indexOf('?') + 1); | ||
var parts = qp.split('&'); | ||
if(parts && parts.length > 0) { | ||
for(var i = 0; i < parts.length; i++) { | ||
var kv = parts[i].split('='); | ||
if(kv && kv.length > 0) { | ||
if (kv[0] === this.name) { | ||
// skip it | ||
return false; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
if (obj.url.indexOf('?') > 0) { | ||
obj.url = obj.url + '&' + this.name + '=' + this.value; | ||
@@ -93,3 +113,5 @@ } else { | ||
} else if (this.type === 'header') { | ||
obj.headers[this.name] = this.value; | ||
if(typeof obj.headers[this.name] === 'undefined') { | ||
obj.headers[this.name] = this.value; | ||
} | ||
@@ -114,4 +136,8 @@ return true; | ||
*/ | ||
var PasswordAuthorization = module.exports.PasswordAuthorization = function (name, username, password) { | ||
this.name = name; | ||
var PasswordAuthorization = module.exports.PasswordAuthorization = function (username, password) { | ||
if (arguments.length === 3) { | ||
helpers.log('PasswordAuthorization: the \'name\' argument has been removed, pass only username and password'); | ||
username = arguments[1]; | ||
password = arguments[2]; | ||
} | ||
this.username = username; | ||
@@ -122,5 +148,7 @@ this.password = password; | ||
PasswordAuthorization.prototype.apply = function (obj) { | ||
obj.headers.Authorization = 'Basic ' + btoa(this.username + ':' + this.password); | ||
if(typeof obj.headers.Authorization === 'undefined') { | ||
obj.headers.Authorization = 'Basic ' + btoa(this.username + ':' + this.password); | ||
} | ||
return true; | ||
}; |
@@ -10,2 +10,3 @@ 'use strict'; | ||
isArray: require('lodash-compat/lang/isArray'), | ||
isObject: require('lodash-compat/lang/isObject'), | ||
isFunction: require('lodash-compat/lang/isFunction'), | ||
@@ -23,2 +24,3 @@ isPlainObject: require('lodash-compat/lang/isPlainObject'), | ||
var SwaggerSpecConverter = require('./spec-converter'); | ||
var Q = require('q'); | ||
@@ -65,2 +67,3 @@ // We have to keep track of the function/property names to avoid collisions for tag names which are used to allow the | ||
'tagFromLabel', | ||
'title', | ||
'url', | ||
@@ -98,2 +101,4 @@ 'useJQuery' | ||
this.useJQuery = false; | ||
this.swaggerObject = {}; | ||
this.deferredClient = Q.defer(); | ||
@@ -115,3 +120,3 @@ this.clientAuthorizations = new auth.SwaggerAuthorizations(); | ||
this.url = url; | ||
} else if (typeof url === 'object') { | ||
} else if (_.isObject(url)) { | ||
options = url; | ||
@@ -127,3 +132,4 @@ this.url = options.url; | ||
this.modelPropertyMacro = options.modelPropertyMacro || null; | ||
this.parameterMacro = options.modelPropertyMacro || null; | ||
this.parameterMacro = options.parameterMacro || null; | ||
this.usePromise = options.usePromise || null; | ||
@@ -141,9 +147,13 @@ if (typeof options.success === 'function') { | ||
this.supportedSubmitMethods = options.supportedSubmitMethods || []; | ||
this.failure = options.failure || function () {}; | ||
this.failure = options.failure || function (err) { throw err; }; | ||
this.progress = options.progress || function () {}; | ||
this.spec = _.cloneDeep(options.spec); // Clone so we do not alter the provided document | ||
if (typeof options.success === 'function') { | ||
if (options.scheme) { | ||
this.scheme = options.scheme; | ||
} | ||
if (this.usePromise || typeof options.success === 'function') { | ||
this.ready = true; | ||
this.build(); | ||
return this.build(); | ||
} | ||
@@ -159,3 +169,3 @@ }; | ||
this.progress('fetching resource list: ' + this.url); | ||
this.progress('fetching resource list: ' + this.url + '; Please wait.'); | ||
@@ -189,2 +199,3 @@ var obj = { | ||
self.swaggerVersion = responseObj.swaggerVersion; | ||
self.swaggerObject = responseObj; | ||
@@ -199,4 +210,7 @@ if (responseObj.swagger && parseInt(responseObj.swagger) === 2) { | ||
var converter = new SwaggerSpecConverter(); | ||
self.oldSwaggerObject = self.swaggerObject; | ||
converter.setDocumentationLocation(self.url); | ||
converter.convert(responseObj, self.clientAuthorizations, function(spec) { | ||
self.swaggerObject = spec; | ||
new Resolver().resolve(spec, self.url, self.buildFromSpec, self); | ||
@@ -211,5 +225,6 @@ self.isValid = true; | ||
if (this.spec) { | ||
self.swaggerObject = this.spec; | ||
setTimeout(function () { | ||
new Resolver().resolve(self.spec, self.buildFromSpec, self); | ||
}, 10); | ||
}, 10); | ||
} else { | ||
@@ -225,3 +240,3 @@ this.clientAuthorizations.apply(obj); | ||
return this; | ||
return (this.usePromise) ? this.deferredClient.promise : this; | ||
}; | ||
@@ -268,5 +283,5 @@ | ||
location = this.parseUri(this.url); | ||
if (typeof this.schemes === 'undefined' || this.schemes.length === 0) { | ||
if (typeof this.scheme === 'undefined' && typeof this.schemes === 'undefined' || this.schemes.length === 0) { | ||
this.scheme = location.scheme || 'http'; | ||
} else { | ||
} else if (typeof this.scheme === 'undefined') { | ||
this.scheme = this.schemes[0]; | ||
@@ -287,3 +302,3 @@ } | ||
} | ||
else { | ||
else if (typeof this.scheme === 'undefined') { | ||
this.scheme = this.schemes[0]; | ||
@@ -337,2 +352,3 @@ } | ||
var operationId = self.idFromOp(path, method, operation); | ||
var operationObject = new Operation(self, | ||
@@ -391,2 +407,4 @@ operation.scheme, | ||
operationId = self.makeUniqueOperationId(operationId, self.apis[apiProperty]); | ||
// Bind tag help | ||
@@ -421,5 +439,11 @@ if (!_.isFunction(operationGroup.help)) { | ||
if (this.success) { | ||
if (this.usePromise) { | ||
this.isValid = true; | ||
this.isBuilt = true; | ||
this.deferredClient.resolve(this); | ||
return this.deferredClient.promise; | ||
} | ||
if (this.success) { | ||
this.success(); | ||
@@ -431,2 +455,24 @@ } | ||
SwaggerClient.prototype.makeUniqueOperationId = function(operationId, api) { | ||
var count = 0; | ||
var name = operationId; | ||
// make unique across this operation group | ||
while(true) { | ||
var matched = false; | ||
_.forEach(api.operations, function (operation) { | ||
if(operation.nickname === name) { | ||
matched = true; | ||
} | ||
}) | ||
if(!matched) { | ||
return name; | ||
} | ||
name = operationId + '_' + count; | ||
count ++; | ||
} | ||
return operationId; | ||
} | ||
SwaggerClient.prototype.parseUri = function (uri) { | ||
@@ -488,9 +534,46 @@ var urlParseRE = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/; | ||
opId = opId.replace(/([_])*$/g, ''); | ||
return opId; | ||
}; | ||
SwaggerClient.prototype.fail = function (message) { | ||
this.failure(message); | ||
SwaggerClient.prototype.setHost = function (host) { | ||
this.host = host; | ||
throw message; | ||
if(this.apis) { | ||
_.forEach(this.apis, function(api) { | ||
if(api.operations) { | ||
_.forEach(api.operations, function(operation) { | ||
operation.host = host; | ||
}); | ||
} | ||
}); | ||
} | ||
}; | ||
SwaggerClient.prototype.setBasePath = function (basePath) { | ||
this.basePath = basePath; | ||
if(this.apis) { | ||
_.forEach(this.apis, function(api) { | ||
if(api.operations) { | ||
_.forEach(api.operations, function(operation) { | ||
operation.basePath = basePath; | ||
}); | ||
} | ||
}); | ||
} | ||
}; | ||
SwaggerClient.prototype.fail = function (message) { | ||
if (this.usePromise) { | ||
this.deferredClient.reject(message); | ||
return this.deferredClient.promise; | ||
} else { | ||
if (this.failure) { | ||
this.failure(message); | ||
} | ||
else { | ||
this.failure(message); | ||
} | ||
} | ||
}; |
'use strict'; | ||
var _ = { | ||
isPlainObject: require('lodash-compat/lang/isPlainObject') | ||
isPlainObject: require('lodash-compat/lang/isPlainObject'), | ||
indexOf: require('lodash-compat/array/indexOf') | ||
}; | ||
@@ -24,3 +25,3 @@ | ||
module.exports.optionHtml = function (label, value) { | ||
var optionHtml = module.exports.optionHtml = function (label, value) { | ||
return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>'; | ||
@@ -37,30 +38,2 @@ }; | ||
module.exports.typeFromJsonSchema = function (type, format) { | ||
var str; | ||
if (type === 'integer' && format === 'int32') { | ||
str = 'integer'; | ||
} else if (type === 'integer' && format === 'int64') { | ||
str = 'long'; | ||
} else if (type === 'integer' && typeof format === 'undefined') { | ||
str = 'long'; | ||
} else if (type === 'string' && format === 'date-time') { | ||
str = 'date-time'; | ||
} else if (type === 'string' && format === 'date') { | ||
str = 'date'; | ||
} else if (type === 'number' && format === 'float') { | ||
str = 'float'; | ||
} else if (type === 'number' && format === 'double') { | ||
str = 'double'; | ||
} else if (type === 'number' && typeof format === 'undefined') { | ||
str = 'double'; | ||
} else if (type === 'boolean') { | ||
str = 'boolean'; | ||
} else if (type === 'string') { | ||
str = 'string'; | ||
} | ||
return str; | ||
}; | ||
var simpleRef = module.exports.simpleRef = function (name) { | ||
@@ -78,44 +51,1 @@ if (typeof name === 'undefined') { | ||
var getStringSignature = module.exports.getStringSignature = function (obj, baseComponent) { | ||
var str = ''; | ||
if (typeof obj.$ref !== 'undefined') { | ||
str += simpleRef(obj.$ref); | ||
} else if (typeof obj.type === 'undefined') { | ||
str += 'object'; | ||
} else if (obj.type === 'array') { | ||
if (baseComponent) { | ||
str += getStringSignature((obj.items || obj.$ref || {})); | ||
} else { | ||
str += 'Array['; | ||
str += getStringSignature((obj.items || obj.$ref || {})); | ||
str += ']'; | ||
} | ||
} else if (obj.type === 'integer' && obj.format === 'int32') { | ||
str += 'integer'; | ||
} else if (obj.type === 'integer' && obj.format === 'int64') { | ||
str += 'long'; | ||
} else if (obj.type === 'integer' && typeof obj.format === 'undefined') { | ||
str += 'long'; | ||
} else if (obj.type === 'string' && obj.format === 'date-time') { | ||
str += 'date-time'; | ||
} else if (obj.type === 'string' && obj.format === 'date') { | ||
str += 'date'; | ||
} else if (obj.type === 'string' && typeof obj.format === 'undefined') { | ||
str += 'string'; | ||
} else if (obj.type === 'number' && obj.format === 'float') { | ||
str += 'float'; | ||
} else if (obj.type === 'number' && obj.format === 'double') { | ||
str += 'double'; | ||
} else if (obj.type === 'number' && typeof obj.format === 'undefined') { | ||
str += 'double'; | ||
} else if (obj.type === 'boolean') { | ||
str += 'boolean'; | ||
} else if (obj.$ref) { | ||
str += simpleRef(obj.$ref); | ||
} else { | ||
str += obj.type; | ||
} | ||
return str; | ||
}; |
'use strict'; | ||
var helpers = require('./helpers'); | ||
var jQuery = require('jquery'); | ||
var request = require('superagent'); | ||
var jsyaml = require('js-yaml'); | ||
var _ = { | ||
isObject: require('lodash-compat/lang/isObject') | ||
}; | ||
@@ -32,5 +34,15 @@ /* | ||
} | ||
client.opts = opts || {}; | ||
// legacy support | ||
if ((obj && obj.useJQuery === true) || this.isInternetExplorer()) { | ||
var hasJQuery = false; | ||
if(typeof window !== 'undefined') { | ||
if(typeof window.jQuery !== 'undefined') { | ||
hasJQuery = true; | ||
} | ||
} | ||
if(this.isInternetExplorer() && (obj.useJQuery === false || !hasJquery )) { | ||
throw new Exception('Unsupported configuration! JQuery is required but not available'); | ||
} | ||
if ((obj && obj.useJQuery === true) || this.isInternetExplorer() && hasJQuery) { | ||
client = new JQueryHttpClient(opts); | ||
@@ -41,2 +53,9 @@ } | ||
var requestInterceptor = function(data) { | ||
if(opts && opts.requestInterceptor) { | ||
data = opts.requestInterceptor.apply(data); | ||
} | ||
return data; | ||
} | ||
var responseInterceptor = function(data) { | ||
@@ -46,3 +65,3 @@ if(opts && opts.responseInterceptor) { | ||
} | ||
success(data); | ||
return success(data); | ||
}; | ||
@@ -55,3 +74,3 @@ | ||
if (obj && typeof obj.body === 'object') { | ||
if (_.isObject(obj) && _.isObject(obj.body)) { | ||
// special processing for file uploads via jquery | ||
@@ -67,3 +86,6 @@ if (obj.body.type && obj.body.type === 'formData'){ | ||
} | ||
client.execute(obj); | ||
client.execute(requestInterceptor(obj)); | ||
return (obj.deferred) ? obj.deferred.promise : obj; | ||
}; | ||
@@ -90,2 +112,3 @@ | ||
JQueryHttpClient.prototype.execute = function (obj) { | ||
var jq = jQuery || window.jQuery; | ||
var cb = obj.on; | ||
@@ -155,4 +178,2 @@ var request = obj; | ||
var contentType = (headers['content-type'] || headers['Content-Type'] || null); | ||
try { | ||
@@ -178,5 +199,5 @@ var possibleObj = response.responseJSON || jsyaml.safeLoad(response.responseText); | ||
jQuery.support.cors = true; | ||
jq.support.cors = true; | ||
return jQuery.ajax(obj); | ||
return jq.ajax(obj); | ||
}; | ||
@@ -193,4 +214,2 @@ | ||
var name; | ||
var accept = headers.accept || headers.Accept; | ||
for (name in headers) { | ||
@@ -225,5 +244,15 @@ r.set(name, headers[name]); | ||
if (err && obj.on && obj.on.error) { | ||
response.obj = err; | ||
response.errObj = err; | ||
response.status = res ? res.status : 500; | ||
response.statusText = res ? res.text : err.message; | ||
if(res.headers && res.headers['content-type']) { | ||
if(res.headers['content-type'].indexOf('application/json') >= 0) { | ||
try { | ||
response.obj = JSON.parse(response.statusText); | ||
} | ||
catch (e) { | ||
response.obj = null; | ||
} | ||
} | ||
} | ||
cb = obj.on.error; | ||
@@ -247,3 +276,3 @@ } else if (res && obj.on && obj.on.response) { | ||
// null means we can't parse into object | ||
response.obj = possibleObj || null; | ||
response.obj = (typeof possibleObj === 'object') ? possibleObj : null; | ||
@@ -250,0 +279,0 @@ response.status = res.status; |
'use strict'; | ||
var SwaggerHttp = require('./http'); | ||
var _ = { | ||
isObject: require('lodash-compat/lang/isObject'), | ||
cloneDeep: require('lodash-compat/lang/cloneDeep'), | ||
isArray: require('lodash-compat/lang/isArray') | ||
}; | ||
/** | ||
/** | ||
* Resolves a spec's remote references | ||
@@ -10,3 +16,22 @@ */ | ||
Resolver.prototype.processAllOf = function(name, definition, resolutionTable, unresolvedRefs, spec) { | ||
var i, location, property; | ||
definition['x-resolved-from'] = [ '#/definitions/' + name ]; | ||
var allOf = definition.allOf; | ||
// the refs go first | ||
allOf.sort(function(a, b) { | ||
if(a.$ref && b.$ref) { return 0; } | ||
else if(a.$ref) { return -1; } | ||
else { return 1; } | ||
}); | ||
for (i = 0; i < allOf.length; i++) { | ||
property = allOf[i]; | ||
location = '/definitions/' + name + '/allOf'; | ||
this.resolveInline(null, spec, property, resolutionTable, unresolvedRefs, location); | ||
} | ||
}; | ||
Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) { | ||
this.spec = spec; | ||
var root = arg1, callback = arg2, scope = arg3, location, i; | ||
@@ -26,2 +51,3 @@ if(typeof arg1 === 'function') { | ||
spec.definitions = spec.definitions || {}; | ||
// definitions | ||
@@ -32,18 +58,12 @@ for (name in spec.definitions) { | ||
property = definition.properties[propertyName]; | ||
this.resolveTo(root, property, resolutionTable, '/definitions'); | ||
if(_.isArray(property.allOf)) { | ||
this.processAllOf(name, property, resolutionTable, unresolvedRefs, spec); | ||
} | ||
else { | ||
this.resolveTo(root, property, resolutionTable, '/definitions'); | ||
} | ||
} | ||
if(definition.allOf) { | ||
var allOf = definition.allOf; | ||
// the refs go first | ||
allOf.sort(function(a, b) { | ||
if(a.$ref && b.$ref) { return 0; } | ||
else if(a.$ref) { return -1; } | ||
else { return 1; } | ||
}); | ||
for (i = 0; i < allOf.length; i++) { | ||
property = allOf[i]; | ||
location = '/definitions/' + name + '/allOf'; | ||
this.resolveInline(null, spec, property, resolutionTable, unresolvedRefs, location); | ||
} | ||
this.processAllOf(name, definition, resolutionTable, unresolvedRefs, spec); | ||
} | ||
@@ -66,4 +86,10 @@ } | ||
operation = path[method]; | ||
var sharedParameters = path.parameters || []; | ||
var parameters = operation.parameters || []; | ||
var parameters = operation.parameters; | ||
for (i in sharedParameters) { | ||
var parameter = sharedParameters[i]; | ||
parameters.unshift(parameter); | ||
} | ||
for (i in parameters) { | ||
@@ -74,3 +100,23 @@ var parameter = parameters[i]; | ||
if (parameter.in === 'body' && parameter.schema) { | ||
this.resolveTo(root, parameter.schema, resolutionTable, location); | ||
if(_.isArray(parameter.schema.allOf)) { | ||
// move to a definition | ||
var modelName = 'inline_model'; | ||
var name = modelName; | ||
var done = false; var counter = 0; | ||
while(!done) { | ||
if(typeof spec.definitions[name] === 'undefined') { | ||
done = true; | ||
break; | ||
} | ||
name = modelName + '_' + counter; | ||
counter ++; | ||
} | ||
spec.definitions[name] = { allOf: parameter.schema.allOf }; | ||
delete parameter.schema.allOf; | ||
parameter.schema.$ref = '#/definitions/' + name; | ||
this.processAllOf(name, spec.definitions[name], resolutionTable, unresolvedRefs, spec); | ||
} | ||
else { | ||
this.resolveTo(root, parameter.schema, resolutionTable, location); | ||
} | ||
} | ||
@@ -88,3 +134,3 @@ | ||
if(typeof response === 'object') { | ||
if(_.isObject(response)) { | ||
if(response.$ref) { | ||
@@ -101,2 +147,4 @@ // response reference | ||
} | ||
// clear them out to avoid multiple resolutions | ||
path.parameters = []; | ||
} | ||
@@ -108,2 +156,3 @@ | ||
var parts; | ||
for(i = 0; i < all.length; i++) { | ||
@@ -139,3 +188,3 @@ var a = all[i]; | ||
else { | ||
var parts = a.key.split('#'); | ||
parts = a.key.split('#'); | ||
if(parts.length === 2) { | ||
@@ -170,2 +219,13 @@ if(parts[0].indexOf('http://') === 0 || parts[0].indexOf('https://') === 0) { | ||
if (a.resolveAs === 'inline') { | ||
if(a.key && a.key.indexOf('#') === -1 && a.key.charAt(0) !== '/') { | ||
// handle relative schema | ||
parts = a.root.split('/'); | ||
location = ''; | ||
for(i = 0; i < parts.length - 1; i++) { | ||
location += parts[i] + '/'; | ||
} | ||
location += a.key; | ||
a.root = location; | ||
a.location = ''; | ||
} | ||
toResolve.push(a); | ||
@@ -183,4 +243,4 @@ } | ||
for(var ii = 0; ii < toResolve.length; ii++) { | ||
(function(item, self) { | ||
if(item.root === null) { | ||
(function(item, spec, self) { | ||
if(item.root === null || item.root === root) { | ||
// local resolve | ||
@@ -205,3 +265,6 @@ self.resolveItem(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, item); | ||
processedCalls += 1; | ||
unresolvedRefs[item.key] = null; | ||
unresolvedRefs[item.key] = { | ||
root: item.root, | ||
location: item.location | ||
}; | ||
@@ -214,3 +277,3 @@ if (processedCalls === expectedCalls) { | ||
var swagger = response.obj; | ||
self.resolveItem(swagger, _root, resolutionTable, resolvedRefs, unresolvedRefs, item); | ||
self.resolveItem(swagger, item.root, resolutionTable, resolvedRefs, unresolvedRefs, item); | ||
processedCalls += 1; | ||
@@ -230,3 +293,3 @@ | ||
} | ||
}(toResolve[ii], this)); | ||
}(toResolve[ii], spec, this)); | ||
} | ||
@@ -242,20 +305,22 @@ | ||
var location = spec, parts = path.split('/'); | ||
for (var j = 0; j < parts.length; j++) { | ||
var segment = parts[j]; | ||
if(segment.indexOf('~1') !== -1) { | ||
segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/'); | ||
if(segment.charAt(0) !== '/') { | ||
segment = '/' + segment; | ||
if(path !== '') { | ||
for (var j = 0; j < parts.length; j++) { | ||
var segment = parts[j]; | ||
if (segment.indexOf('~1') !== -1) { | ||
segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/'); | ||
if (segment.charAt(0) !== '/') { | ||
segment = '/' + segment; | ||
} | ||
} | ||
if (typeof location === 'undefined' || location === null) { | ||
break; | ||
} | ||
if (segment === '' && j === (parts.length - 1) && parts.length > 1) { | ||
location = null; | ||
break; | ||
} | ||
if (segment.length > 0) { | ||
location = location[segment]; | ||
} | ||
} | ||
if (typeof location === 'undefined') { | ||
break; | ||
} | ||
if(segment === '' && j === (parts.length - 1) && parts.length > 1) { | ||
location = null; | ||
break; | ||
} | ||
if (segment.length > 0) { | ||
location = location[segment]; | ||
} | ||
} | ||
@@ -296,2 +361,5 @@ var resolved = item.key; | ||
if (item.resolveAs === 'ref') { | ||
for (key in resolvedTo.obj) { | ||
var abs = this.retainRoot(resolvedTo.obj[key], item.root); | ||
} | ||
spec.definitions[resolvedTo.name] = resolvedTo.obj; | ||
@@ -338,3 +406,3 @@ item.obj.$ref = '#/definitions/' + resolvedTo.name; | ||
// verify possible keys | ||
for(i in keys) { | ||
for (i = 0; i < keys.length; i++) { | ||
var part = keys[i]; | ||
@@ -344,3 +412,3 @@ var parts = part.split('/'); | ||
for(var k in parts) { | ||
for (var k = 0; k < parts.length; k++) { | ||
var key = parts[k]; | ||
@@ -363,2 +431,5 @@ if(key !== '') { | ||
for(var key in obj) { | ||
if (!obj.hasOwnProperty(key)) { | ||
continue; | ||
} | ||
var item = obj[key]; | ||
@@ -368,3 +439,3 @@ if(key === '$ref' && typeof item === 'string') { | ||
} | ||
else if(typeof item === 'object') { | ||
else if(_.isObject(item)) { | ||
var o = this.getRefs(item); | ||
@@ -393,3 +464,3 @@ for(var k in o) { | ||
} | ||
else if(typeof item === 'object') { | ||
else if(_.isObject(item)) { | ||
this.retainRoot(item, root); | ||
@@ -471,3 +542,4 @@ } | ||
} | ||
} else if (property.type === 'array') { | ||
} | ||
else if (property.type === 'array') { | ||
this.resolveTo(root, property.items, resolutionTable, location); | ||
@@ -478,10 +550,49 @@ } | ||
Resolver.prototype.resolveTo = function (root, property, resolutionTable, location) { | ||
var sp, i; | ||
var ref = property.$ref; | ||
var lroot = root; | ||
if (typeof ref !== 'undefined') { | ||
if(ref.indexOf('#') >= 0) { | ||
var parts = ref.split('#'); | ||
if (ref) { | ||
if(ref.indexOf('#') >= 0) { | ||
location = ref.split('#')[1]; | ||
// #/definitions/foo | ||
// foo.json#/bar | ||
if(parts[0] && ref.indexOf('/') === 0) { | ||
} | ||
else if(parts[0] && parts[0].indexOf('http') === 0) { | ||
lroot = parts[0]; | ||
ref = parts[1]; | ||
} | ||
else if(parts[0] && parts[0].length > 0) { | ||
// relative file | ||
sp = root.split('/'); | ||
lroot = ''; | ||
for(i = 0; i < sp.length - 1; i++) { | ||
lroot += sp[i] + '/'; | ||
} | ||
lroot += parts[0]; | ||
} | ||
else { | ||
} | ||
location = parts[1]; | ||
} | ||
else if (ref.indexOf('http://') === 0 || ref.indexOf('https://') === 0) { | ||
lroot = ref; | ||
location = ''; | ||
} | ||
else { | ||
// relative file | ||
sp = root.split('/'); | ||
lroot = ''; | ||
for(i = 0; i < sp.length - 1; i++) { | ||
lroot += sp[i] + '/'; | ||
} | ||
lroot += ref; | ||
location = ''; | ||
} | ||
resolutionTable.push({ | ||
obj: property, resolveAs: 'ref', root: root, key: ref, location: location | ||
obj: property, resolveAs: 'ref', root: lroot, key: ref, location: location | ||
}); | ||
@@ -491,5 +602,25 @@ } else if (property.type === 'array') { | ||
this.resolveTo(root, items, resolutionTable, location); | ||
} else { | ||
if(property && property.properties) { | ||
var name = this.uniqueName("inline_model"); | ||
this.spec.definitions[name] = _.cloneDeep(property); | ||
property['$ref'] = '#/definitions/' + name; | ||
delete property.type; | ||
delete property.properties; | ||
} | ||
} | ||
}; | ||
Resolver.prototype.uniqueName = function(base) { | ||
var name = base; | ||
var count = 0; | ||
while(true) { | ||
if(!_.isObject(this.spec.definitions[name])) { | ||
return name; | ||
} | ||
name = base + '_' + count; | ||
count++; | ||
} | ||
} | ||
Resolver.prototype.resolveAllOf = function(spec, obj, depth) { | ||
@@ -500,8 +631,24 @@ depth = depth || 0; | ||
for(var key in obj) { | ||
if (!obj.hasOwnProperty(key)) { | ||
continue; | ||
} | ||
var item = obj[key]; | ||
if(item === null) { | ||
throw new TypeError('Swagger 2.0 does not support null types (' + obj + '). See https://github.com/swagger-api/swagger-spec/issues/229.'); | ||
} | ||
if(typeof item === 'object') { | ||
this.resolveAllOf(spec, item, depth + 1); | ||
} | ||
if(item && typeof item.allOf !== 'undefined') { | ||
var allOf = item.allOf; | ||
if(Array.isArray(allOf)) { | ||
if(_.isArray(allOf)) { | ||
var output = {}; | ||
output['x-composed'] = true; | ||
if (typeof item['x-resolved-from'] !== 'undefined') { | ||
output['x-resolved-from'] = item['x-resolved-from']; | ||
} | ||
output.properties = {}; | ||
if ( item.example ){ | ||
output.example = item.example; | ||
} | ||
for(var i = 0; i < allOf.length; i++) { | ||
@@ -516,3 +663,3 @@ var component = allOf[i]; | ||
if(!output.hasOwnProperty(part)) { | ||
output[part] = component[part]; | ||
output[part] = JSON.parse(JSON.stringify(component[part])); | ||
if(part === 'properties') { | ||
@@ -528,4 +675,8 @@ for(name in output[part]) { | ||
for(name in properties) { | ||
output.properties[name] = properties[name]; | ||
output.properties[name]['x-resolved-from'] = source; | ||
output.properties[name] = JSON.parse(JSON.stringify(properties[name])); | ||
var resolvedFrom = properties[name]['x-resolved-from']; | ||
if (typeof resolvedFrom === 'undefined' || resolvedFrom === 'self') { | ||
resolvedFrom = source; | ||
} | ||
output.properties[name]['x-resolved-from'] = resolvedFrom; | ||
} | ||
@@ -556,3 +707,3 @@ } | ||
} | ||
if(typeof item === 'object') { | ||
if(_.isObject(item)) { | ||
this.resolveAllOf(spec, item, depth + 1); | ||
@@ -559,0 +710,0 @@ } |
'use strict'; | ||
var SwaggerHttp = require('./http'); | ||
var _ = { | ||
isObject: require('lodash-compat/lang/isObject') | ||
}; | ||
@@ -41,7 +44,2 @@ var SwaggerSpecConverter = module.exports = function () { | ||
// take basePath into account | ||
if (obj.basePath) { | ||
this.setDocumentationLocation(obj.basePath); | ||
} | ||
// see if this is a single-file swagger definition | ||
@@ -109,3 +107,3 @@ var isSingleFileSwagger = false; | ||
// build a mapping of id to name for 1.0 model resolutions | ||
if(typeof obj === 'object') { | ||
if(_.isObject(obj)) { | ||
for(name in obj.models) { | ||
@@ -130,3 +128,3 @@ var existingModel = obj.models[name]; | ||
SwaggerSpecConverter.prototype.models = function(obj, swagger) { | ||
if(typeof obj !== 'object') { | ||
if(!_.isObject(obj)) { | ||
return; | ||
@@ -273,3 +271,3 @@ } | ||
SwaggerSpecConverter.prototype.responseMessages = function(operation, existingOperation) { | ||
if(typeof existingOperation !== 'object') { | ||
if(!_.isObject(existingOperation)) { | ||
return; | ||
@@ -317,3 +315,3 @@ } | ||
// TODO | ||
if(typeof obj !== 'object') { | ||
if(!_.isObject(obj)) { | ||
return; | ||
@@ -364,2 +362,5 @@ } | ||
} | ||
if(typeof existingParameter.defaultValue !== 'undefined') { | ||
parameter.default = existingParameter.defaultValue; | ||
} | ||
@@ -372,3 +373,3 @@ operation.parameters = operation.parameters || []; | ||
SwaggerSpecConverter.prototype.dataType = function(source, target) { | ||
if(typeof source !== 'object') { | ||
if(!_.isObject(source)) { | ||
return; | ||
@@ -383,2 +384,5 @@ } | ||
} | ||
if (source.format) { | ||
target.format = source.format; | ||
} | ||
@@ -420,22 +424,23 @@ // default can be 'false' | ||
return {type: 'array', items: jsonType}; | ||
} | ||
else if(lcType === 'int' || (lcType === 'integer' && format === 'int32')) | ||
} else if(lcType === 'int' || (lcType === 'integer' && format === 'int32')) { | ||
{return {type: 'integer', format: 'int32'};} | ||
else if(lcType === 'long' || (lcType === 'integer' && format === 'int64')) | ||
} else if(lcType === 'long' || (lcType === 'integer' && format === 'int64')) { | ||
{return {type: 'integer', format: 'int64'};} | ||
else if(lcType === 'integer') | ||
} else if(lcType === 'integer') { | ||
{return {type: 'integer', format: 'int64'};} | ||
else if(lcType === 'float' || (lcType === 'number' && format === 'float')) | ||
} else if(lcType === 'float' || (lcType === 'number' && format === 'float')) { | ||
{return {type: 'number', format: 'float'};} | ||
else if(lcType === 'double' || (lcType === 'number' && format === 'double')) | ||
} else if(lcType === 'double' || (lcType === 'number' && format === 'double')) { | ||
{return {type: 'number', format: 'double'};} | ||
else if((lcType === 'string' && format === 'date-time') || (lcType === 'date')) | ||
} else if((lcType === 'string' && format === 'date-time') || (lcType === 'date')) { | ||
{return {type: 'string', format: 'date-time'};} | ||
else if(lcType === 'string') | ||
} else if(lcType === 'string') { | ||
{return {type: 'string'};} | ||
else if(lcType === 'file') | ||
} else if(lcType === 'file') { | ||
{return {type: 'file'};} | ||
else if(lcType === 'boolean') | ||
} else if(lcType === 'boolean') { | ||
{return {type: 'boolean'};} | ||
else if(lcType === 'array' || lcType === 'list') { | ||
} else if(lcType === 'boolean') { | ||
{return {type: 'boolean'};} | ||
} else if(lcType === 'array' || lcType === 'list') { | ||
if(source.items) { | ||
@@ -448,10 +453,12 @@ var it = this.toJsonSchema(source.items); | ||
} | ||
} | ||
else if(source.$ref) { | ||
return {$ref: '#/definitions/' + this.modelMap[source.$ref] || source.$ref}; | ||
} | ||
else if(lcType === 'void' || lcType === '') | ||
} else if(source.$ref) { | ||
return {$ref: this.modelMap[source.$ref] ? '#/definitions/' + this.modelMap[source.$ref] : source.$ref}; | ||
} else if(lcType === 'void' || lcType === '') { | ||
{return {};} | ||
else { | ||
return {$ref: '#/definitions/' + this.modelMap[source.type] || source.type}; | ||
} else if (this.modelMap[source.type]) { | ||
// If this a model using `type` instead of `$ref`, that's fine. | ||
return {$ref: '#/definitions/' + this.modelMap[source.type]}; | ||
} else { | ||
// Unknown model type or 'object', pass it along. | ||
return {type: source.type}; | ||
} | ||
@@ -458,0 +465,0 @@ }; |
'use strict'; | ||
var _ = { | ||
cloneDeep: require('lodash-compat/lang/cloneDeep'), | ||
forEach: require('lodash-compat/collection/forEach'), | ||
indexOf: require('lodash-compat/array/indexOf'), | ||
isArray: require('lodash-compat/lang/isArray'), | ||
isPlainObject: require('lodash-compat/lang/isPlainObject'), | ||
isString: require('lodash-compat/lang/isString'), | ||
isUndefined: require('lodash-compat/lang/isUndefined'), | ||
keys: require('lodash-compat/object/keys'), | ||
map: require('lodash-compat/collection/map') | ||
}; | ||
var helpers = require('../helpers'); | ||
var SchemaMarkup = require('../schema-markup.js'); | ||
var jsyaml = require('js-yaml'); | ||
@@ -29,373 +23,2 @@ | ||
var schemaToHTML = function (name, schema, models, modelPropertyMacro) { | ||
var strongOpen = '<span class="strong">'; | ||
var strongClose = '</span>'; | ||
var references = {}; | ||
var seenModels = []; | ||
var inlineModels = 0; | ||
var addReference = function (schema, name, skipRef) { | ||
var modelName = name; | ||
var model; | ||
if (schema.$ref) { | ||
modelName = schema.title || helpers.simpleRef(schema.$ref); | ||
model = models[modelName]; | ||
} else if (_.isUndefined(name)) { | ||
modelName = schema.title || 'Inline Model ' + (++inlineModels); | ||
model = new Model(modelName, schema, models, modelPropertyMacro); | ||
} | ||
if (skipRef !== true) { | ||
references[modelName] = _.isUndefined(model) ? {} : model.definition; | ||
} | ||
return modelName; | ||
}; | ||
var primitiveToHTML = function (schema) { | ||
var html = '<span class="propType">'; | ||
var type = schema.type || 'object'; | ||
if (schema.$ref) { | ||
html += addReference(schema, helpers.simpleRef(schema.$ref)); | ||
} else if (type === 'object') { | ||
if (!_.isUndefined(schema.properties)) { | ||
html += addReference(schema); | ||
} else { | ||
html += 'object'; | ||
} | ||
} else if (type === 'array') { | ||
html += 'Array['; | ||
if (_.isArray(schema.items)) { | ||
html += _.map(schema.items, addReference).join(','); | ||
} else if (_.isPlainObject(schema.items)) { | ||
if (_.isUndefined(schema.items.$ref)) { | ||
if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) { | ||
html += schema.items.type; | ||
} else { | ||
html += addReference(schema.items); | ||
} | ||
} else { | ||
html += addReference(schema.items, helpers.simpleRef(schema.items.$ref)); | ||
} | ||
} else { | ||
helpers.log('Array type\'s \'items\' schema is not an array or an object, cannot process'); | ||
html += 'object'; | ||
} | ||
html += ']'; | ||
} else { | ||
html += schema.type; | ||
} | ||
html += '</span>'; | ||
return html; | ||
}; | ||
var primitiveToOptionsHTML = function (schema, html) { | ||
var options = ''; | ||
var type = schema.type || 'object'; | ||
var isArray = type === 'array'; | ||
if (isArray) { | ||
if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) { | ||
type = schema.items.type; | ||
} else { | ||
type = 'object'; | ||
} | ||
} | ||
if (!_.isUndefined(schema.default)) { | ||
options += helpers.optionHtml('Default', schema.default); | ||
} | ||
switch (type) { | ||
case 'string': | ||
if (schema.minLength) { | ||
options += helpers.optionHtml('Min. Length', schema.minLength); | ||
} | ||
if (schema.maxLength) { | ||
options += helpers.optionHtml('Max. Length', schema.maxLength); | ||
} | ||
if (schema.pattern) { | ||
options += helpers.optionHtml('Reg. Exp.', schema.pattern); | ||
} | ||
break; | ||
case 'integer': | ||
case 'number': | ||
if (schema.minimum) { | ||
options += helpers.optionHtml('Min. Value', schema.minimum); | ||
} | ||
if (schema.exclusiveMinimum) { | ||
options += helpers.optionHtml('Exclusive Min.', 'true'); | ||
} | ||
if (schema.maximum) { | ||
options += helpers.optionHtml('Max. Value', schema.maximum); | ||
} | ||
if (schema.exclusiveMaximum) { | ||
options += helpers.optionHtml('Exclusive Max.', 'true'); | ||
} | ||
if (schema.multipleOf) { | ||
options += helpers.optionHtml('Multiple Of', schema.multipleOf); | ||
} | ||
break; | ||
} | ||
if (isArray) { | ||
if (schema.minItems) { | ||
options += helpers.optionHtml('Min. Items', schema.minItems); | ||
} | ||
if (schema.maxItems) { | ||
options += helpers.optionHtml('Max. Items', schema.maxItems); | ||
} | ||
if (schema.uniqueItems) { | ||
options += helpers.optionHtml('Unique Items', 'true'); | ||
} | ||
if (schema.collectionFormat) { | ||
options += helpers.optionHtml('Coll. Format', schema.collectionFormat); | ||
} | ||
} | ||
if (_.isUndefined(schema.items)) { | ||
if (_.isArray(schema.enum)) { | ||
var enumString; | ||
if (type === 'number' || type === 'integer') { | ||
enumString = schema.enum.join(', '); | ||
} else { | ||
enumString = '"' + schema.enum.join('", "') + '"'; | ||
} | ||
options += helpers.optionHtml('Enum', enumString); | ||
} | ||
} | ||
if (options.length > 0) { | ||
html = '<span class="propWrap">' + html + '<table class="optionsWrapper"><tr><th colspan="2">' + type + '</th></tr>' + options + '</table></span>'; | ||
} | ||
return html; | ||
}; | ||
var processModel = function (schema, name) { | ||
var type = schema.type || 'object'; | ||
var isArray = schema.type === 'array'; | ||
var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose; | ||
if (name) { | ||
seenModels.push(name); | ||
} | ||
if (isArray) { | ||
if (_.isArray(schema.items)) { | ||
html += '<div>' + _.map(schema.items, function (item) { | ||
var type = item.type || 'object'; | ||
if (_.isUndefined(item.$ref)) { | ||
if (_.indexOf(['array', 'object'], type) > -1) { | ||
if (type === 'object' && _.isUndefined(item.properties)) { | ||
return 'object'; | ||
} else { | ||
return addReference(item); | ||
} | ||
} else { | ||
return primitiveToOptionsHTML(item, type); | ||
} | ||
} else { | ||
return addReference(item, helpers.simpleRef(item.$ref)); | ||
} | ||
}).join(',</div><div>'); | ||
} else if (_.isPlainObject(schema.items)) { | ||
if (_.isUndefined(schema.items.$ref)) { | ||
if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) { | ||
if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) { | ||
html += '<div>object</div>'; | ||
} else { | ||
html += '<div>' + addReference(schema.items) + '</div>'; | ||
} | ||
} else { | ||
html += '<div>' + primitiveToOptionsHTML(schema.items, schema.items.type) + '</div>'; | ||
} | ||
} else { | ||
html += '<div>' + addReference(schema.items, helpers.simpleRef(schema.items.$ref)) + '</div>'; | ||
} | ||
} else { | ||
helpers.log('Array type\'s \'items\' property is not an array or an object, cannot process'); | ||
html += '<div>object</div>'; | ||
} | ||
} else { | ||
if (schema.$ref) { | ||
html += '<div>' + addReference(schema, name) + '</div>'; | ||
} else if (type === 'object') { | ||
html += '<div>'; | ||
if (_.isPlainObject(schema.properties)) { | ||
html += _.map(schema.properties, function (property, name) { | ||
var propertyIsRequired = (_.indexOf(schema.required, name) >= 0); | ||
var cProperty = _.cloneDeep(property); | ||
var requiredClass = propertyIsRequired ? 'required' : ''; | ||
var html = '<span class="propName ' + requiredClass + '">' + name + '</span> ('; | ||
var model; | ||
// Allow macro to set the default value | ||
cProperty.default = modelPropertyMacro(cProperty); | ||
// Resolve the schema (Handle nested schemas) | ||
cProperty = helpers.resolveSchema(cProperty); | ||
// We need to handle property references to primitives (Issue 339) | ||
if (!_.isUndefined(cProperty.$ref)) { | ||
model = models[helpers.simpleRef(cProperty.$ref)]; | ||
if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) { | ||
// Use referenced schema | ||
cProperty = helpers.resolveSchema(model.definition); | ||
} | ||
} | ||
html += primitiveToHTML(cProperty); | ||
if(!propertyIsRequired) { | ||
html += ', <span class="propOptKey">optional</span>'; | ||
} | ||
html += ')'; | ||
if (!_.isUndefined(cProperty.description)) { | ||
html += ': ' + '<span class="propDesc">' + cProperty.description + '</span>'; | ||
} | ||
if (cProperty.enum) { | ||
html += ' = <span class="propVals">[\'' + cProperty.enum.join('\', \'') + '\']</span>'; | ||
} | ||
return primitiveToOptionsHTML(cProperty, html); | ||
}).join(',</div><div>'); | ||
} | ||
html += '</div>'; | ||
} else { | ||
html += '<div>' + primitiveToOptionsHTML(schema, type) + '</div>'; | ||
} | ||
} | ||
return html + strongOpen + (isArray ? ']' : '}') + strongClose; | ||
}; | ||
// Resolve the schema (Handle nested schemas) | ||
schema = helpers.resolveSchema(schema); | ||
// Generate current HTML | ||
var html = processModel(schema, name); | ||
// Generate references HTML | ||
while (_.keys(references).length > 0) { | ||
/* jshint ignore:start */ | ||
_.forEach(references, function (schema, name) { | ||
var seenModel = _.indexOf(seenModels, name) > -1; | ||
delete references[name]; | ||
if (!seenModel) { | ||
seenModels.push(name); | ||
html += '<br />' + processModel(schema, name); | ||
} | ||
}); | ||
/* jshint ignore:end */ | ||
} | ||
return html; | ||
}; | ||
var schemaToJSON = function (schema, models, modelsToIgnore, modelPropertyMacro) { | ||
// Resolve the schema (Handle nested schemas) | ||
schema = helpers.resolveSchema(schema); | ||
var type = schema.type || 'object'; | ||
var format = schema.format; | ||
var model; | ||
var output; | ||
if (schema.example) { | ||
output = schema.example; | ||
} else if (_.isUndefined(schema.items) && _.isArray(schema.enum)) { | ||
output = schema.enum[0]; | ||
} | ||
if (_.isUndefined(output)) { | ||
if (schema.$ref) { | ||
model = models[helpers.simpleRef(schema.$ref)]; | ||
if (!_.isUndefined(model)) { | ||
if (_.isUndefined(modelsToIgnore[model.name])) { | ||
modelsToIgnore[model.name] = model; | ||
output = schemaToJSON(model.definition, models, modelsToIgnore, modelPropertyMacro); | ||
delete modelsToIgnore[model.name]; | ||
} else { | ||
if (model.type === 'array') { | ||
output = []; | ||
} else { | ||
output = {}; | ||
} | ||
} | ||
} | ||
} else if (!_.isUndefined(schema.default)) { | ||
output = schema.default; | ||
} else if (type === 'string') { | ||
if (format === 'date-time') { | ||
output = new Date().toISOString(); | ||
} else if (format === 'date') { | ||
output = new Date().toISOString().split('T')[0]; | ||
} else { | ||
output = 'string'; | ||
} | ||
} else if (type === 'integer') { | ||
output = 0; | ||
} else if (type === 'number') { | ||
output = 0.0; | ||
} else if (type === 'boolean') { | ||
output = true; | ||
} else if (type === 'object') { | ||
output = {}; | ||
_.forEach(schema.properties, function (property, name) { | ||
var cProperty = _.cloneDeep(property); | ||
// Allow macro to set the default value | ||
cProperty.default = modelPropertyMacro(property); | ||
output[name] = schemaToJSON(cProperty, models, modelsToIgnore, modelPropertyMacro); | ||
}); | ||
} else if (type === 'array') { | ||
output = []; | ||
if (_.isArray(schema.items)) { | ||
_.forEach(schema.items, function (item) { | ||
output.push(schemaToJSON(item, models, modelsToIgnore, modelPropertyMacro)); | ||
}); | ||
} else if (_.isPlainObject(schema.items)) { | ||
output.push(schemaToJSON(schema.items, models, modelsToIgnore, modelPropertyMacro)); | ||
} else if (_.isUndefined(schema.items)) { | ||
output.push({}); | ||
} else { | ||
helpers.log('Array type\'s \'items\' property is not an array or an object, cannot process'); | ||
} | ||
} | ||
} | ||
return output; | ||
}; | ||
Model.prototype.createJSONSample = Model.prototype.getSampleValue = function (modelsToIgnore) { | ||
@@ -417,7 +40,7 @@ modelsToIgnore = modelsToIgnore || {}; | ||
return schemaToJSON(this.definition, this.models, modelsToIgnore, this.modelPropertyMacro); | ||
return SchemaMarkup.schemaToJSON(this.definition, this.models, modelsToIgnore, this.modelPropertyMacro); | ||
}; | ||
Model.prototype.getMockSignature = function () { | ||
return schemaToHTML(this.name, this.definition, this.models, this.modelPropertyMacro); | ||
return SchemaMarkup.schemaToHTML(this.name, this.definition, this.models, this.modelPropertyMacro); | ||
}; |
@@ -6,3 +6,4 @@ 'use strict'; | ||
isUndefined: require('lodash-compat/lang/isUndefined'), | ||
isEmpty: require('lodash-compat/lang/isEmpty') | ||
isEmpty: require('lodash-compat/lang/isEmpty'), | ||
isObject: require('lodash-compat/lang/isObject') | ||
}; | ||
@@ -12,2 +13,3 @@ var helpers = require('../helpers'); | ||
var SwaggerHttp = require('../http'); | ||
var Q = require('q'); | ||
@@ -42,3 +44,3 @@ var Operation = module.exports = function (parent, scheme, operationId, httpMethod, path, args, definitions, models, clientAuthorizations) { | ||
this.scheme = scheme || parent.scheme || 'http'; | ||
this.schemes = parent.schemes; | ||
this.schemes = args.schemes || parent.schemes; | ||
this.security = args.security; | ||
@@ -48,3 +50,3 @@ this.summary = args.summary || ''; | ||
this.useJQuery = parent.useJQuery; | ||
this.parameterMacro = parent.parameterMacro || function (parameter) { | ||
this.parameterMacro = parent.parameterMacro || function (operation, parameter) { | ||
return parameter.default; | ||
@@ -85,2 +87,5 @@ }; | ||
} | ||
else { | ||
definitions = {}; | ||
} | ||
@@ -91,3 +96,3 @@ for (i = 0; i < this.parameters.length; i++) { | ||
// Allow macro to set the default value | ||
param.default = this.parameterMacro(param); | ||
param.default = this.parameterMacro(this, param); | ||
@@ -98,5 +103,5 @@ if (param.type === 'array') { | ||
// the enum can be defined at the items level | ||
if (param.items && param.items.enum) { | ||
param['enum'] = param.items.enum; | ||
} | ||
//if (param.items && param.items.enum) { | ||
// param['enum'] = param.items.enum; | ||
//} | ||
} | ||
@@ -112,2 +117,9 @@ | ||
if(param['x-examples']) { | ||
var d = param['x-examples'].default; | ||
if(typeof d !== 'undefined') { | ||
param.default = d; | ||
} | ||
} | ||
if (typeof param['enum'] !== 'undefined') { | ||
@@ -502,3 +514,3 @@ var id; | ||
Operation.prototype.getBody = function (headers, args, opts) { | ||
var formParams = {}, body, key, value, hasBody = false; | ||
var formParams = {}, hasFormParams, body, key, value, hasBody = false; | ||
@@ -513,2 +525,3 @@ for (var i = 0; i < this.parameters.length; i++) { | ||
formParams[param.name] = args[param.name]; | ||
hasFormParams = true; | ||
} | ||
@@ -532,3 +545,3 @@ } | ||
// handle form params | ||
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') { | ||
if (hasFormParams) { | ||
var encoded = ''; | ||
@@ -599,3 +612,3 @@ | ||
return sampleJson; | ||
} else if (typeof sampleJson === 'object') { | ||
} else if (_.isObject(sampleJson)) { | ||
var t = sampleJson; | ||
@@ -607,3 +620,3 @@ | ||
if (t.nodeName) { | ||
if (t.nodeName && typeof t === 'Node') { | ||
var xmlString = new XMLSerializer().serializeToString(t); | ||
@@ -633,5 +646,5 @@ | ||
var args = arg1 || {}; | ||
var opts = {}, success, error; | ||
var opts = {}, success, error, deferred; | ||
if (typeof arg2 === 'object') { | ||
if (_.isObject(arg2)) { | ||
opts = arg2; | ||
@@ -645,7 +658,12 @@ success = arg3; | ||
} | ||
if(this.responseInterceptor) { | ||
// add the request interceptor from parent, if none sent from client | ||
if(!opts.requestInterceptor && this.requestInterceptor ) { | ||
opts.requestInterceptor = this.requestInterceptor ; | ||
} | ||
if(!opts.responseInterceptor && this.responseInterceptor) { | ||
opts.responseInterceptor = this.responseInterceptor; | ||
} | ||
if (typeof arg2 === 'function') { | ||
@@ -656,4 +674,8 @@ success = arg2; | ||
success = (success || this.parent.defaultSuccessCallback || helpers.log); | ||
error = (error || this.parent.defaultErrorCallback || helpers.log); | ||
if (this.parent.usePromise) { | ||
deferred = Q.defer(); | ||
} else { | ||
success = (success || this.parent.defaultSuccessCallback || helpers.log); | ||
error = (error || this.parent.defaultErrorCallback || helpers.log); | ||
} | ||
@@ -670,5 +692,10 @@ | ||
helpers.fail(message); | ||
error(message); | ||
return; | ||
if (this.parent.usePromise) { | ||
deferred.reject(message); | ||
return deferred.promise; | ||
} else { | ||
error(message); | ||
return {}; | ||
} | ||
} | ||
@@ -703,9 +730,20 @@ | ||
useJQuery: opts.useJQuery, | ||
deferred: deferred, | ||
headers: headers, | ||
on: { | ||
response: function (response) { | ||
return success(response, parent); | ||
if (deferred) { | ||
deferred.resolve(response); | ||
return deferred.promise; | ||
} else { | ||
return success(response, parent); | ||
} | ||
}, | ||
error: function (response) { | ||
return error(response, parent); | ||
if (deferred) { | ||
deferred.reject(response); | ||
return deferred.promise; | ||
} else { | ||
return error(response, parent); | ||
} | ||
} | ||
@@ -719,3 +757,3 @@ } | ||
} else { | ||
new SwaggerHttp().execute(obj, opts); | ||
return new SwaggerHttp().execute(obj, opts); | ||
} | ||
@@ -775,3 +813,4 @@ }; | ||
// if there's a body, need to set the consumes header via requestContentType | ||
if (this.method === 'post' || this.method === 'put' || this.method === 'patch') { | ||
if (this.method === 'post' || this.method === 'put' || this.method === 'patch' || | ||
((this.method === 'delete' || this.method === 'get') && body) ) { | ||
if (opts.requestContentType) { | ||
@@ -818,3 +857,3 @@ consumes = opts.requestContentType; | ||
* Returns true if the request accepts header matches anything in this.produces. | ||
* If this.produces contains * / *, ignore the accept header. | ||
* If this.produces contains * / *, ignore the accept header. | ||
* @param {string=} accepts The client request accept header. | ||
@@ -831,6 +870,12 @@ * @return {boolean} | ||
Operation.prototype.asCurl = function (args) { | ||
var obj = this.execute(args, {mock: true}); | ||
Operation.prototype.asCurl = function (args1, args2) { | ||
var opts = {mock: true}; | ||
if (typeof args2 === 'object') { | ||
for (var argKey in args2) { | ||
opts[argKey] = args2[argKey]; | ||
} | ||
} | ||
var obj = this.execute(args1, opts); | ||
this.clientAuthorizations.apply(obj); | ||
this.clientAuthorizations.apply(obj, this.operation.security); | ||
@@ -841,7 +886,11 @@ var results = []; | ||
if (obj.headers) { | ||
if (typeof obj.headers !== 'undefined') { | ||
var key; | ||
for (key in obj.headers) { | ||
results.push('--header "' + key + ': ' + obj.headers[key] + '"'); | ||
var value = obj.headers[key]; | ||
if(typeof value === 'string'){ | ||
value = value.replace(/\'/g, '\\u0027'); | ||
} | ||
results.push('--header \'' + key + ': ' + value + '\''); | ||
} | ||
@@ -853,3 +902,3 @@ } | ||
if (typeof obj.body === 'object') { | ||
if (_.isObject(obj.body)) { | ||
body = JSON.stringify(obj.body); | ||
@@ -860,3 +909,3 @@ } else { | ||
results.push('-d "' + body.replace(/"/g, '\\"') + '"'); | ||
results.push('-d \'' + body.replace(/\'/g, '\\u0027') + '\''); | ||
} | ||
@@ -863,0 +912,0 @@ |
@@ -11,3 +11,3 @@ { | ||
"description": "swagger-client is a javascript client for use with swaggering APIs.", | ||
"version": "2.1.7-M2", | ||
"version": "2.1.7", | ||
"homepage": "http://swagger.io", | ||
@@ -37,5 +37,5 @@ "repository": { | ||
"cookiejar": "^2.0.1", | ||
"jquery": "^2.1.3", | ||
"js-yaml": "^3.3.0", | ||
"lodash-compat": "^3.5.0", | ||
"q": "^1.4.1", | ||
"superagent": "^1.2" | ||
@@ -73,3 +73,3 @@ }, | ||
}, | ||
"license": "apache 2.0" | ||
"license": "Apache-2.0" | ||
} |
# Swagger JS library | ||
[![Build Status](https://api.travis-ci.org/swagger-api/swagger-js.png)](https://travis-ci.org/swagger-api/swagger-js) | ||
[![Build Status](https://travis-ci.org/swagger-api/swagger-js.svg?branch=master)](https://travis-ci.org/swagger-api/swagger-js) | ||
@@ -18,2 +18,8 @@ This is the Swagger javascript client for use with [swagger](http://swagger.io) enabled APIs. | ||
or: | ||
``` | ||
bower install swagger-js | ||
``` | ||
Then let swagger do the work! | ||
@@ -33,3 +39,4 @@ ```js | ||
NOTE: we're explicitly setting the responseContentType, because we don't want you getting stuck when there is more than one content type available. | ||
NOTE: we're explicitly setting the responseContentType, because we don't want you getting stuck when | ||
there is more than one content type available. | ||
@@ -64,5 +71,45 @@ That's it! You'll get a JSON response with the default callback handler: | ||
Need to pass an API key? Configure one as a querystring: | ||
### Handling success and failures | ||
You need to pass success and error functions to do anything reasonable with the responses: | ||
```js | ||
var client = require('swagger-client'); | ||
var swagger = new client({ | ||
url: 'http://petstore.swagger.io/v2/swagger.json', | ||
success: function() { | ||
swagger.pet.getPetById({petId:7}, function(success){ | ||
console.log('succeeded and returned this object: ' + success.obj); | ||
}, | ||
function(error) { | ||
console.log('failed with the following: ' + error.statusText); | ||
}); | ||
} | ||
}); | ||
``` | ||
You can use promises too, by passing the `usePromise: true` option: | ||
```js | ||
var Swagger = require('swagger-client'); | ||
new Swagger({ | ||
url: 'http://petstore.swagger.io/v2/swagger.json', | ||
usePromise: true | ||
}) | ||
.then(function(client) { | ||
client.pet.getPetById({petId:7}) | ||
.then(function(pet) { | ||
console.log(pet.obj); | ||
}) | ||
.catch(function(error) { | ||
console.log('Oops! failed with message: ' + error.statusText); | ||
}); | ||
}); | ||
``` | ||
Need to pass an API key? Configure one as a query string: | ||
```js | ||
client.clientAuthorizations.add("apiKey", new client.ApiKeyAuthorization("api_key","special-key","query")); | ||
@@ -77,2 +124,17 @@ ``` | ||
...or with the swagger-client constructor: | ||
```js | ||
var swagger = new client({ | ||
url: 'http://example.com/spec.json', | ||
success: function() {}, | ||
authorizations : { | ||
easyapi_basic: new client.PasswordAuthorization('<username>', '<password>'), | ||
someHeaderAuth: new client.ApiKeyAuthorization('<nameOfHeader>', '<value>', 'header'), | ||
someQueryAuth: new client.ApiKeyAuthorization('<nameOfQueryKey>', '<value>', 'query'), | ||
someCookieAuth: new client.CookieAuthorization('<cookie>'), | ||
} | ||
}); | ||
``` | ||
### Calling an API with swagger + the browser! | ||
@@ -87,6 +149,6 @@ | ||
window.swagger = new SwaggerClient({ | ||
url: "http://petstore.swagger.io/api/api-docs", | ||
url: "http://petstore.swagger.io/v2/swagger.json", | ||
success: function() { | ||
// upon connect, fetch a pet and set contents to element "mydata" | ||
swagger.apis.pet.getPetById({petId:1},{responseContentType: 'application/json'}, function(data) { | ||
swagger.pet.getPetById({petId:1},{responseContentType: 'application/json'}, function(data) { | ||
document.getElementById("mydata").innerHTML = JSON.stringify(data.obj); | ||
@@ -142,3 +204,3 @@ }); | ||
In the above simple example, we're creating a new request signer that simply | ||
base 64 encodes the URL. Of course you'd do something more sophisticated, but | ||
Base64 encodes the URL. Of course you'd do something more sophisticated, but | ||
after encoding it, a header called `signature` is set before sending the request. | ||
@@ -161,3 +223,3 @@ | ||
Please [fork the code](https://github.com/swagger-api/swagger-js) and help us improve | ||
swagger-client.js. Send us a pull request to the `develop_2.0` branch! Tests make merges get accepted more quickly. | ||
swagger-client.js. Send us a pull request to the `master` branch! Tests make merges get accepted more quickly. | ||
@@ -164,0 +226,0 @@ swagger-js use gulp for Node.js. |
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 too big to display
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
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
High entropy strings
Supply chain riskContains high entropy strings. This could be a sign of encrypted data, leaked secrets or obfuscated code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
High entropy strings
Supply chain riskContains high entropy strings. This could be a sign of encrypted data, leaked secrets or obfuscated code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
17
267
1
2700394
31065
1
11
+ Addedq@^1.4.1
+ Addedq@1.5.1(transitive)
- Removedjquery@^2.1.3
- Removedjquery@2.2.4(transitive)