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

swagger-tools

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

swagger-tools - npm Package Compare versions

Comparing version 0.6.13 to 0.7.0

middleware/1.2/swagger-security.js

99

index.js
/*
* The MIT License (MIT)
*
*
* Copyright (c) 2014 Apigee Corporation
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy

@@ -12,6 +12,6 @@ * of this software and associated documentation files (the "Software"), to deal

* furnished to do so, subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

@@ -28,5 +28,94 @@ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

var _ = require('lodash');
var helpers = require('./lib/helpers');
var initializeMiddleware = function initializeMiddleware (rlOrSO, resources, callback) {
var args;
var spec;
var swaggerVersion;
if (_.isUndefined(rlOrSO)) {
throw new Error('rlOrSO is required');
} else if (!_.isPlainObject(rlOrSO)) {
throw new TypeError('rlOrSO must be an object');
}
args = [rlOrSO];
swaggerVersion = helpers.getSwaggerVersion(rlOrSO);
if (!swaggerVersion) {
throw new Error('Unable to identify the Swagger version based on rlOrSO');
} else if (swaggerVersion === '1.2') {
if (_.isUndefined(resources)) {
throw new Error('resources is required');
} else if (!_.isArray(resources)) {
throw new TypeError('resources must be an array');
}
args.push(resources);
} else {
callback = arguments[1];
}
if (_.isUndefined(callback)) {
throw new Error('callback is required');
} else if (!_.isFunction(callback)) {
throw new TypeError('callback must be a function');
}
args.push(function (err, results) {
if (results && results.errors.length + _.reduce(results.apiDeclarations || [], function (count, apiDeclaration) {
return count += (apiDeclaration ? apiDeclaration.errors.length : 0);
}, 0) > 0) {
err = new Error('Swagger document(s) failed validation so the server cannot start');
err.results = results;
}
if (err) {
if (process.env.NODE_ENV === 'test') {
throw err;
} else {
return helpers.printValidationResults(swaggerVersion, rlOrSO, resources, results, true, true);
}
}
callback({
// Create a wrapper to avoid having to pass the non-optional arguments back to the swaggerMetadata middleware
swaggerMetadata: function () {
var swaggerMetadata = require('./middleware/' + swaggerVersion + '/swagger-metadata');
return swaggerMetadata.apply(undefined, args.slice(0, args.length - 1));
},
swaggerRouter: require('./middleware/' + swaggerVersion + '/swagger-router'),
swaggerSecurity: require('./middleware/' + swaggerVersion + '/swagger-security'),
// Create a wrapper to avoid having to pass the non-optional arguments back to the swaggerUi middleware
swaggerUi: function (options) {
var swaggerUi = require('./middleware/' + swaggerVersion + '/swagger-ui');
var suArgs = [rlOrSO];
if (swaggerVersion === '1.2') {
suArgs.push(_.reduce(resources, function (map, resource) {
map[resource.resourcePath] = resource;
return map;
}, {}));
}
suArgs.push(options || {});
return swaggerUi.apply(undefined, suArgs);
},
swaggerValidator: require('./middleware/' + swaggerVersion + '/swagger-validator')
});
});
spec = helpers.getSpec(helpers.getSwaggerVersion(rlOrSO));
spec.validate.apply(spec, args);
};
module.exports = {
middleware: require('./middleware'),
initializeMiddleware: initializeMiddleware,
specs: require('./lib/specs')
};

@@ -28,4 +28,60 @@ /*

var _ = require('lodash');
var JsonRefs = require('json-refs');
var ZSchema = require('z-schema');
var draft04Json = require('../schemas/json-schema-draft-04.json');
var draft04Url = 'http://json-schema.org/draft-04/schema';
var specCache = {};
module.exports.createJsonValidator = function createJsonValidator (schemas) {
var validator = new ZSchema({
reportPathAsArray: true
});
var result;
// Add the draft-04 spec
validator.setRemoteReference(draft04Url, draft04Json);
// Swagger uses some unsupported/invalid formats so just make them all pass
_.each(['byte', 'double', 'float', 'int32', 'int64', 'mime-type', 'uri-template'], function (format) {
ZSchema.registerFormat(format, function () {
return true;
});
});
// Compile and validate the schemas
if (!_.isUndefined(schemas)) {
result = validator.compileSchema(schemas);
// If there is an error, it's unrecoverable so just blow the eff up
if (result === false) {
console.error('JSON Schema file' + (schemas.length > 1 ? 's are' : ' is') + ' invalid:');
_.each(validator.getLastErrors(), function (err) {
console.error(' ' + (_.isArray(err.path) ? JsonRefs.pathToPointer(err.path) : err.path) + ': ' + err.message);
});
throw new Error('Unable to create validator due to invalid JSON Schema');
}
}
return validator;
};
module.exports.formatResults = function formatResults (results) {
if (results) {
// Update the results based on its content to indicate success/failure accordingly
return results.errors.length + results.warnings.length +
_.reduce(results.apiDeclarations, function (count, aResult) {
if (aResult) {
count += aResult.errors.length + aResult.warnings.length;
}
return count;
}, 0) > 0 ? results : undefined;
}
return results;
};
/**

@@ -59,20 +115,10 @@ * Returns the proper specification based on the human readable version.

/**
* Takes a reference and creates a fully qualified JSON pointer from it. (2.0 only)
* Atempts to figure out the Swagger version from the Swagger document.
*
* If the passed in reference is fully qualified, it is returned as-is. Otherwise, the reference will have
* '#/definitions/' prepended to it to make it fully qualified since these 'relative' references are only allowed for
* model definitions.
* @param {object} document - The Swagger document
*
* @param {string} ref - The relative or fully qualified reference
*
* @returns the corresponding JSON pointer for the reference
* @returns the Swagger version or undefined if the document is not a Swagger document
*/
module.exports.refToJsonPointer = function refToJsonPointer (ref) {
// TODO: Fix this to handle remote references
if (ref.charAt(0) !== '#') {
ref = '#/definitions/' + ref;
}
return ref;
module.exports.getSwaggerVersion = function getSwaggerVersion (document) {
return _.isPlainObject(document) ? document.swaggerVersion || document.swagger : undefined;
};

@@ -87,3 +133,3 @@

*/
module.exports.toJsonPointer = function toJsonPointer (path) {
var toJsonPointer = module.exports.toJsonPointer = function toJsonPointer (path) {
// http://tools.ietf.org/html/rfc6901#section-4

@@ -94,1 +140,73 @@ return '#/' + path.map(function (part) {

};
module.exports.printValidationResults = function printValidationResults (version, apiDOrSO, apiDeclarations, results,
printSummary, endProcess) {
var pluralize = function pluralize (string, count) {
return count === 1 ? string : string + 's';
};
var printErrorsOrWarnings = function printErrorsOrWarnings (header, entries, indent) {
console.error(header);
console.error();
_.each(entries, function (entry) {
console.error(new Array(indent + 1).join(' ') + toJsonPointer(entry.path) + ': ' + entry.message);
if (entry.inner) {
printErrorsOrWarnings (header, entry.inner, indent + 2);
}
});
console.error();
};
var errorCount = 0;
var warningCount = 0;
console.error();
if (results.errors.length > 0) {
errorCount += results.errors.length;
printErrorsOrWarnings('API Errors:', results.errors, 2);
}
if (results.warnings.length > 0) {
warningCount += results.warnings.length;
printErrorsOrWarnings('API Warnings:', results.warnings, 2);
}
if (results.apiDeclarations) {
results.apiDeclarations.forEach(function (adResult, index) {
if (!adResult) {
return;
}
var name = apiDeclarations[index].resourcePath || index;
if (adResult.errors.length > 0) {
errorCount += adResult.errors.length;
printErrorsOrWarnings(' API Declaration (' + name + ') Errors:', adResult.errors, 4);
}
if (adResult.warnings.length > 0) {
warningCount += adResult.warnings.length;
printErrorsOrWarnings(' API Declaration (' + name + ') Warnings:', adResult.warnings, 4);
}
});
}
if (printSummary) {
if (errorCount > 0) {
console.error(errorCount + ' ' + pluralize('error', errorCount) + ' and ' + warningCount + ' ' +
pluralize('warning', warningCount));
} else {
console.error('Validation succeeded but with ' + warningCount + ' ' + pluralize('warning', warningCount));
}
}
if (errorCount > 0 && endProcess) {
process.exit(1);
}
};

2005

lib/specs.js

@@ -28,55 +28,53 @@ /*

var _ = require('lodash');
var jjv = require('jjv');
var jjve = require('jjve');
var md5 = require('spark-md5');
var async = require('async');
var helpers = require('./helpers');
var JsonRefs = require('json-refs');
var SparkMD5 = require('spark-md5');
var traverse = require('traverse');
var helpers = require('./helpers');
var validators = require('./validators');
var draft04Json = require('../schemas/json-schema-draft-04.json');
var draft04Url = 'http://json-schema.org/draft-04/schema';
var jjvOptions = {
checkRequired: true,
removeAdditional: false,
useDefault: false,
useCoerce: false
};
var jjveOptions = {
formatPath: false
};
var metadataCache = {};
var refToJsonPointer = helpers.refToJsonPointer;
var toJsonPointer = helpers.toJsonPointer;
var documentCache = {};
var createValidator = function createValidator (spec, schemaNames) {
var validator = jjv(jjvOptions);
var addExternalRefsToValidator = function addExternalRefsToValidator (validator, json, callback) {
var remoteRefs = _.reduce(JsonRefs.findRefs(json), function (rRefs, ref, ptr) {
if (JsonRefs.isRemotePointer(ptr)) {
rRefs.push(ref.split('#')[0]);
}
// Disable the 'uri' format checker as it's got issues: https://github.com/acornejo/jjv/issues/24
validator.addFormat('uri', function() {
return true;
});
return rRefs;
}, []);
var resolveRemoteRefs = function (ref, callback) {
JsonRefs.resolveRefs({$ref: ref}, function (err, json) {
if (err) {
return callback(err);
}
validator.addSchema(draft04Url, draft04Json);
// Perform the same for the newly resolved document
addExternalRefsToValidator(validator, json, function (err, rJson) {
callback (err, rJson);
});
});
};
if (!_.isUndefined(schemaNames)) {
// Compile the necessary schemas
_.each(schemaNames, function (schemaName) {
var clone = _.cloneDeep(spec.schemas[schemaName]);
if (remoteRefs.length > 0) {
async.map(remoteRefs, resolveRemoteRefs, function (err, results) {
if (err) {
return callback(err);
}
clone.id = schemaName;
_.each(results, function (json, index) {
validator.setRemoteReference(remoteRefs[index], json);
});
validator.addSchema(schemaName, clone);
}.bind(this));
callback();
});
} else {
callback();
}
validator.je = jjve(validator);
return validator;
};
var createErrorOrWarning = function createErrorOrWarning (code, message, data, path, dest) {
var createErrorOrWarning = function createErrorOrWarning (code, message, path, dest) {
dest.push({
code: code,
message: message,
data: data,
path: path

@@ -86,204 +84,169 @@ });

var createUnusedErrorOrWarning = function createUnusedErrorOrWarning (data, val, codeSuffix, msgPrefix, path, dest) {
createErrorOrWarning('UNUSED_' + codeSuffix, msgPrefix + ' is defined but is not used: ' + val, data, path, dest);
};
var addReference = function addReference (cacheEntry, defPathOrPtr, refPathOrPtr, results, omitError) {
var result = true;
var swaggerVersion = helpers.getSwaggerVersion(cacheEntry.resolved);
var defPath = _.isArray(defPathOrPtr) ? defPathOrPtr : JsonRefs.pathFromPointer(defPathOrPtr);
var defPtr = _.isArray(defPathOrPtr) ? JsonRefs.pathToPointer(defPathOrPtr) : defPathOrPtr;
var refPath = _.isArray(refPathOrPtr) ? refPathOrPtr : JsonRefs.pathFromPointer(refPathOrPtr);
var refPtr = _.isArray(refPathOrPtr) ? JsonRefs.pathToPointer(refPathOrPtr) : refPathOrPtr;
var code;
var def;
var displayId;
var msgPrefix;
var type;
var validateExist = function validateExist (data, val, codeSuffix, msgPrefix, path, dest) {
if (!_.isUndefined(data) && data.indexOf(val) === -1) {
createErrorOrWarning('UNRESOLVABLE_' + codeSuffix, msgPrefix + ' could not be resolved: ' + val, val, path, dest);
// Only possible when defPathOrPtr is a string and is not a real pointer
if (defPath.length === 0) {
createErrorOrWarning('INVALID_REFERENCE', 'Not a valid JSON Reference', refPath, results.errors);
return false;
}
};
var validateNoExist = function validateNoExist (data, val, codeSuffix, msgPrefix, path, dest) {
if (!_.isUndefined(data) && data.indexOf(val) > -1) {
createErrorOrWarning('DUPLICATE_' + codeSuffix, msgPrefix + ' already defined: ' + val, val, path, dest);
def = cacheEntry.definitions[defPtr];
type = defPath[0];
code = type === 'securityDefinitions' ?
'SECURITY_DEFINITION' :
type.substring(0, type.length - 1).toUpperCase();
displayId = swaggerVersion === '1.2' ? defPath[defPath.length - 1] : defPtr;
msgPrefix = type === 'securityDefinitions' ?
'Security definition' :
code.charAt(0) + code.substring(1).toLowerCase();
// This is an authorization scope reference
if (['authorizations', 'securityDefinitions'].indexOf(defPath[0]) > -1 && defPath[2] === 'scopes') {
code += '_SCOPE';
msgPrefix += ' scope';
}
};
var validateNoDuplicates = function validateNoDuplicates (data, codeSuffix, msgPrefix, path, dest) {
var name = path[path.length - 1];
if (_.isUndefined(def)) {
if (!omitError) {
createErrorOrWarning('UNRESOLVABLE_' + code, msgPrefix + ' could not be resolved: ' + displayId,
refPath, results.errors);
}
if (!_.isUndefined(data) && data.length !== _.uniq(data).length) {
createErrorOrWarning('DUPLICATE_' + codeSuffix, msgPrefix + ' ' + name + ' has duplicate items', data, path, dest);
result = false;
} else {
if (_.isUndefined(def.references)) {
def.references = [];
}
def.references.push(refPtr);
}
};
var validateArrayType = function validateArrayType (data, path, dest) {
// We have to do this manually for now (https://github.com/swagger-api/swagger-spec/issues/174)
if (data.type === 'array' && _.isUndefined(data.items)) {
createErrorOrWarning('OBJECT_MISSING_REQUIRED_PROPERTY', 'Missing required property: items', data, path, dest);
}
return result;
};
// TODO: Move this to a helper
var getOrComposeSchema = function getOrComposeSchema (documentMetadata, modelId) {
var title = 'Composed ' + (documentMetadata.swaggerVersion === '1.2' ?
JsonRefs.pathFromPointer(modelId).pop() :
modelId);
var metadata = documentMetadata.definitions[modelId];
var originalT = traverse(documentMetadata.original);
var resolvedT = traverse(documentMetadata.resolved);
var composed;
var original;
var validateParameterConstraints = function validateParameterConstraints (spec, parameter, val, path, dest) {
switch (spec.version) {
case '1.2':
// TODO: Make this work with parameters that have references
if (!metadata) {
return undefined;
}
validateArrayType(parameter, path, dest);
original = _.cloneDeep(originalT.get(JsonRefs.pathFromPointer(modelId)));
composed = _.cloneDeep(resolvedT.get(JsonRefs.pathFromPointer(modelId)));
// Validate the value type/format (Skip for array since we manually handle it above for now)
if (parameter.type === 'array' && !_.isUndefined(parameter.items)) {
try {
validators.validateTypeAndFormat(parameter.name, val,
parameter.type === 'array' ? parameter.items.type : parameter.type,
parameter.type === 'array' && parameter.items.format ?
parameter.items.format :
parameter.format);
} catch (err) {
// TODO: Update to notify of 'INVALID_FORMAT'
createErrorOrWarning ('INVALID_TYPE', err.message, val, path, dest);
return;
}
}
// Convert the Swagger 1.2 document to a valid JSON Schema file
if (documentMetadata.swaggerVersion === '1.2') {
// Create inheritance model
if (metadata.lineage.length > 0) {
composed.allOf = [];
// Validate enum
try {
validators.validateEnum(parameter.name, val, parameter.enum);
} catch (err) {
createErrorOrWarning ('ENUM_MISMATCH', err.message, val, path, dest);
return;
_.each(metadata.lineage, function (modelId) {
composed.allOf.push(getOrComposeSchema(documentMetadata, modelId));
});
}
// Validate maximum
try {
validators.validateMaximum(parameter.name, val, parameter.maximum, parameter.type);
} catch (err) {
createErrorOrWarning ('MAXIMUM', err.message, val, path, dest);
return;
}
// Remove the subTypes property
delete composed.subTypes;
// Validate minimum
try {
validators.validateMinimum(parameter.name, val, parameter.minimum, parameter.type);
} catch (err) {
createErrorOrWarning ('MINIMUM', err.message, val, path, dest);
return;
}
_.each(composed.properties, function (property, name) {
var oProp = original.properties[name];
// Validate uniqueItems
try {
validators.validateUniqueItems(parameter.name, val, parameter.uniqueItems);
} catch (err) {
createErrorOrWarning ('ARRAY_UNIQUE', err.message, val, path, dest);
return;
}
// Convert the string values to numerical values
_.each(['maximum', 'minimum'], function (prop) {
if (_.isString(property[prop])) {
property[prop] = parseFloat(property[prop]);
}
});
break;
_.each(JsonRefs.findRefs(oProp), function (ref, ptr) {
var modelId = '#/models/' + ref;
var dMetadata = documentMetadata.definitions[modelId];
var path = JsonRefs.pathFromPointer(ptr);
case '2.0':
// TODO: Make this work with parameters that have schemas/references
if (dMetadata.lineage.length > 0) {
traverse(property).set(path.slice(0, path.length - 1), getOrComposeSchema(documentMetadata, modelId));
} else {
traverse(property).set(path.slice(0, path.length - 1).concat('title'), 'Composed ' + ref);
traverse(property).set(path.slice(0, path.length - 1).concat('type'), 'object');
}
});
});
}
validateArrayType(parameter, path, dest);
// Validate the value type/format (Skip for array since we manually handle it above for now)
if (parameter.type === 'array' && !_.isUndefined(parameter.items)) {
try {
validators.validateTypeAndFormat(parameter.name, val,
parameter.type === 'array' ? parameter.items.type : parameter.type,
parameter.type === 'array' && parameter.items.format ?
parameter.items.format :
parameter.format);
} catch (err) {
// TODO: Update to notify of 'INVALID_FORMAT'
createErrorOrWarning('INVALID_TYPE', err.message, val, path, dest);
return;
}
// Scrub id properties
composed = traverse(composed).map(function (val) {
if (this.key === 'id' && _.isString(val)) {
this.remove();
}
});
// Validate enum
try {
validators.validateEnum(parameter.name, val, parameter.enum);
} catch (err) {
createErrorOrWarning('ENUM_MISMATCH', err.message, val, path, dest);
return;
}
composed.title = title;
composed.type = 'object';
// Validate maximum
try {
validators.validateMaximum(parameter.name, val, parameter.maximum, parameter.type, parameter.exclusiveMaximum);
} catch (err) {
createErrorOrWarning(parameter.exclusiveMaximum === true ? 'MAXIMUM_EXCLUSIVE' : 'MAXIMUM', err.message, val,
path, dest);
return;
}
return composed;
};
// Validate maximum items
try {
validators.validateMaxItems(parameter.name, val, parameter.maxItems);
} catch (err) {
createErrorOrWarning('ARRAY_LENGTH_LONG', err.message, val, path, dest);
return;
}
var createUnusedErrorOrWarning = function createUnusedErrorOrWarning (val, codeSuffix, msgPrefix, path, dest) {
createErrorOrWarning('UNUSED_' + codeSuffix, msgPrefix + ' is defined but is not used: ' + val, path, dest);
};
// Validate maximum length
try {
validators.validateMaxLength(parameter.name, val, parameter.maxLength);
} catch (err) {
createErrorOrWarning('MAX_LENGTH', err.message, val, path, dest);
return;
}
var getDocumentCache = function getDocumentCache (apiDOrSO) {
var key = SparkMD5.hash(JSON.stringify(apiDOrSO));
var cacheEntry = documentCache[key] || _.find(documentCache, function (cacheEntry) {
return cacheEntry.resolvedId === key;
});
// Validate minimum
try {
validators.validateMinimum(parameter.name, val, parameter.minimum, parameter.type, parameter.exclusiveMinimum);
} catch (err) {
createErrorOrWarning(parameter.exclusiveMinimum === 'true' ? 'MINIMUM_EXCLUSIVE' : 'MINIMUM', err.message, val,
path, dest);
return;
}
if (!cacheEntry) {
cacheEntry = documentCache[key] = {
definitions: {},
original: apiDOrSO,
resolved: undefined,
swaggerVersion: helpers.getSwaggerVersion(apiDOrSO)
};
}
// Validate minimum items
try {
validators.validateMinItems(parameter.name, val, parameter.minItems);
} catch (err) {
createErrorOrWarning('ARRAY_LENGTH_SHORT', err.message, val, path, dest);
return;
}
return cacheEntry;
};
// Validate minimum length
try {
validators.validateMinLength(parameter.name, val, parameter.minLength);
} catch (err) {
createErrorOrWarning('MIN_LENGTH', err.message, val, path, dest);
return;
}
var handleValidationError = function handleValidationError (results, callback) {
var err = new Error('The Swagger document is invalid and model composition is not possible');
// Validate pattern
try {
validators.validatePattern(parameter.name, val, parameter.pattern);
} catch (err) {
createErrorOrWarning('PATTERN', err.message, val, path, dest);
return;
}
err.errors = results.errors;
err.warnings = results.warnings;
// Validate uniqueItems
try {
validators.validateUniqueItems(parameter.name, val, parameter.uniqueItems);
} catch (err) {
createErrorOrWarning('ARRAY_UNIQUE', err.message, val, path, dest);
return;
}
break;
}
callback(err);
};
var normalizePath = function normalizePath (path) {
var matches = path.match(/\{(.*?)\}/g);
var argNames = [];
var segments = [];
var normPath = path;
_.each(path.split('/'), function (segment) {
if (segment.charAt(0) === '{') {
argNames.push(segment.substring(1).split('}')[0]);
if (matches) {
_.each(matches, function (match, index) {
normPath = normPath.replace(match, '{' + index + '}');
argNames.push(match.replace(/[{}]/g, ''));
});
}
segment = '{' + (argNames.length - 1) + '}';
}
segments.push(segment);
});
return {
path: segments.join('/'),
path: normPath,
args: argNames

@@ -293,221 +256,252 @@ };

/**
* Creates a new Swagger specification object.
*
* @param {string} version - The Swagger version
*
* @constructor
*/
var Specification = function Specification (version) {
var primitives = ['string', 'number', 'boolean', 'integer', 'array'];
var docsUrl;
var schemasUrl;
var validateNoExist = function validateNoExist (data, val, codeSuffix, msgPrefix, path, dest) {
if (!_.isUndefined(data) && data.indexOf(val) > -1) {
createErrorOrWarning('DUPLICATE_' + codeSuffix, msgPrefix + ' already defined: ' + val, path, dest);
}
};
switch (version) {
case '1.2':
docsUrl = 'https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md';
primitives = _.union(primitives, ['void', 'File']);
schemasUrl = 'https://github.com/wordnik/swagger-spec/tree/master/schemas/v1.2';
var validateSchemaConstraints = function validateSchemaConstraints (documentMetadata, schema, path, results, skip) {
try {
validators.validateSchemaConstraints(documentMetadata.swaggerVersion, schema, path, undefined);
} catch (err) {
if (!skip) {
createErrorOrWarning(err.code, err.message, err.path, results.errors);
}
}
};
break;
case '2.0':
docsUrl = 'https://github.com/wordnik/swagger-spec/blob/master/versions/2.0.md';
primitives = _.union(primitives, ['file']);
schemasUrl = 'https://github.com/wordnik/swagger-spec/tree/master/schemas/v2.0';
var processDocument = function processDocument (documentMetadata, results) {
var swaggerVersion = documentMetadata.swaggerVersion;
var getDefinitionMetadata = function getDefinitionMetadata (defPath) {
var defPtr = JsonRefs.pathToPointer(defPath);
var metadata = documentMetadata.definitions[defPtr];
break;
default:
throw new Error(version + ' is an unsupported Swagger specification version');
}
if (!metadata) {
metadata = documentMetadata.definitions[defPtr] = {
references: []
};
this.docsUrl = docsUrl;
this.primitives = primitives;
this.schemasUrl = schemasUrl;
this.version = version;
// For model definitions, add the inheritance properties
if (['definitions', 'models'].indexOf(JsonRefs.pathFromPointer(defPtr)[0]) > -1) {
metadata.cyclical = false;
metadata.lineage = undefined;
metadata.parents = [];
}
}
// Load the schema files
this.schemas = {};
return metadata;
};
var getDisplayId = function getDisplayId (id) {
return swaggerVersion === '1.2' ? JsonRefs.pathFromPointer(id).pop() : id;
};
var walk = function walk (root, id, lineage) {
var definition = documentMetadata.definitions[id || root];
// Create the validators
this.validators = {};
if (definition) {
_.each(definition.parents, function (parent) {
lineage.push(parent);
switch (version) {
case '1.2':
// Here explicitly to allow browserify to work
this.schemas['apiDeclaration.json'] = require('../schemas/1.2/apiDeclaration.json');
this.schemas['authorizationObject.json'] = require('../schemas/1.2/authorizationObject.json');
this.schemas['dataType.json'] = require('../schemas/1.2/dataType.json');
this.schemas['dataTypeBase.json'] = require('../schemas/1.2/dataTypeBase.json');
this.schemas['infoObject.json'] = require('../schemas/1.2/infoObject.json');
this.schemas['modelsObject.json'] = require('../schemas/1.2/modelsObject.json');
this.schemas['oauth2GrantType.json'] = require('../schemas/1.2/oauth2GrantType.json');
this.schemas['operationObject.json'] = require('../schemas/1.2/operationObject.json');
this.schemas['parameterObject.json'] = require('../schemas/1.2/parameterObject.json');
this.schemas['resourceListing.json'] = require('../schemas/1.2/resourceListing.json');
this.schemas['resourceObject.json'] = require('../schemas/1.2/resourceObject.json');
if (root !== parent) {
walk(root, parent, lineage);
}
});
}
};
var authDefsProp = swaggerVersion === '1.2' ? 'authorizations' : 'securityDefinitions';
var modelDefsProp = swaggerVersion === '1.2' ? 'models' : 'definitions';
this.validators['apiDeclaration.json'] = createValidator(this, [
'dataTypeBase.json',
'modelsObject.json',
'oauth2GrantType.json',
'authorizationObject.json',
'parameterObject.json',
'operationObject.json',
'apiDeclaration.json'
]);
// Process authorization definitions
_.each(documentMetadata.resolved[authDefsProp], function (authorization, name) {
var securityDefPath = [authDefsProp, name];
this.validators['resourceListing.json'] = createValidator(this, [
'resourceObject.json',
'infoObject.json',
'oauth2GrantType.json',
'authorizationObject.json',
'resourceListing.json'
]);
// Swagger 1.2 only has authorization definitions in the Resource Listing
if (swaggerVersion === '1.2' && !authorization.type) {
return;
}
break;
// Create the authorization definition metadata
getDefinitionMetadata(securityDefPath);
case '2.0':
// Here explicitly to allow browserify to work
this.schemas['schema.json'] = require('../schemas/2.0/schema.json');
_.reduce(authorization.scopes, function (seenScopes, scope, indexOrName) {
var scopeName = swaggerVersion === '1.2' ? scope.scope : indexOrName;
var scopeDefPath = securityDefPath.concat(['scopes', indexOrName.toString()]);
var scopeMetadata = getDefinitionMetadata(securityDefPath.concat(['scopes', scopeName]));
this.validators['schema.json'] = createValidator(this, [
'schema.json'
]);
scopeMetadata.scopePath = scopeDefPath;
break;
}
};
// Identify duplicate authorization scope defined in the Resource Listing
validateNoExist(seenScopes, scopeName, 'AUTHORIZATION_SCOPE_DEFINITION', 'Authorization scope definition',
swaggerVersion === '1.2' ? scopeDefPath.concat('scope') : scopeDefPath, results.warnings);
var getModelMetadata = function getModelMetadata (modelsMetadata, modelId) {
var metadata = modelsMetadata[modelId];
seenScopes.push(scopeName);
if (_.isUndefined(metadata)) {
metadata = modelsMetadata[modelId] = {
composed: {},
name: undefined,
parents: [],
refs: [],
schema: undefined
};
}
return seenScopes;
}, []);
});
return metadata;
};
// Proces model definitions
_.each(documentMetadata.resolved[modelDefsProp], function (model, modelId) {
var modelDefPath = [modelDefsProp, modelId];
var modelMetadata = getDefinitionMetadata(modelDefPath);
var processModel = function processModel (spec, modelsMetadata, model, modelId, path, results) {
var metadata = getModelMetadata(modelsMetadata, modelId);
var isRemoteRef = function (ref) {
return ref.indexOf('http://') === 0 || ref.indexOf('https://') === 0;
};
// Identify model id mismatch (Id in models object is not the same as the model's id in the models object)
if (swaggerVersion === '1.2' && modelId !== model.id) {
createErrorOrWarning('MODEL_ID_MISMATCH', 'Model id does not match id in models object: ' + model.id,
modelDefPath.concat('id'), results.errors);
}
// Ensure the model's name and schema are set
metadata.schema = model;
metadata.name = modelId; // Reasonable default
metadata.path = path;
// Do not reprocess parents/references if already processed
if (_.isUndefined(modelMetadata.lineage)) {
// Handle inheritance references
switch (swaggerVersion) {
case '1.2':
_.each(model.subTypes, function (subType, index) {
var subPath = ['models', subType];
var subPtr = JsonRefs.pathToPointer(subPath);
var subMetadata = documentMetadata.definitions[subPtr];
var refPath = modelDefPath.concat(['subTypes', index.toString()]);
switch (spec.version) {
case '1.2':
// Set the model's name to the proper value
metadata.name = path[path.length - 1];
// If the metadata does not yet exist, create it
if (!subMetadata && documentMetadata.resolved[modelDefsProp][subType]) {
subMetadata = getDefinitionMetadata(subPath);
}
// Add model references from properties and validate the default values
_.each(model.properties, function (property, name) {
var pPath = path.concat('properties', name);
// If the reference is valid, add the parent
if (addReference(documentMetadata, subPath, refPath, results)) {
subMetadata.parents.push(JsonRefs.pathToPointer(modelDefPath));
}
});
validateArrayType(property, pPath, results.error);
break;
// Keep track of the model references
if (property.$ref) {
getModelMetadata(modelsMetadata, property.$ref).refs.push(pPath.concat(['$ref']));
} else if (property.type === 'array' && !_.isUndefined(property.items) && !_.isUndefined(property.items.$ref)) {
getModelMetadata(modelsMetadata, property.items.$ref).refs.push(pPath.concat(['items', '$ref']));
default:
_.each(documentMetadata.original[modelDefsProp][modelId].allOf, function (schema, index) {
var childPath = modelDefPath.concat(['allOf', index.toString()]);
var parentMetadata;
var parentPath;
if (_.isUndefined(schema.$ref) || JsonRefs.isRemotePointer(schema.$ref)) {
parentPath = modelDefPath.concat(['allOf', index.toString()]);
} else {
parentMetadata = getDefinitionMetadata(JsonRefs.pathFromPointer(schema.$ref));
parentPath = JsonRefs.pathFromPointer(schema.$ref);
}
modelMetadata.parents.push(JsonRefs.pathToPointer(parentPath));
if (parentMetadata) {
addReference(documentMetadata, parentPath, childPath, results);
}
});
break;
}
}
});
// Validate the default value against constraints
if (!_.isUndefined(property.defaultValue)) {
validateParameterConstraints(spec, property, property.defaultValue, pPath.concat('defaultValue'),
results.errors);
}
switch (swaggerVersion) {
case '2.0':
// Process parameter definitions
_.each(documentMetadata.resolved.parameters, function (parameter, name) {
var path = ['parameters', name];
getDefinitionMetadata(path);
validateSchemaConstraints(documentMetadata, parameter, path, results);
});
// Keep track of model references in subTypes
_.each(_.uniq(model.subTypes), function (subType, index) {
var subMetadata = getModelMetadata(modelsMetadata, subType);
// Process response definitions
_.each(documentMetadata.resolved.responses, function (response, name) {
var path = ['responses', name];
subMetadata.parents.push(modelId);
subMetadata.refs.push(path.concat('subTypes', index.toString()));
getDefinitionMetadata(path);
validateSchemaConstraints(documentMetadata, response, path, results);
});
break;
}
case '2.0':
// Keep track of model references in allOf
_.each(_.uniq(model.allOf), function (schema, index) {
var sPath = path.concat('allOf', index.toString());
// Validate definition/models (Inheritance, property definitions, ...)
_.each(documentMetadata.definitions, function (metadata, id) {
var defPath = JsonRefs.pathFromPointer(id);
var definition = traverse(documentMetadata.original).get(defPath);
var defProp = defPath[0];
var code = defProp.substring(0, defProp.length - 1).toUpperCase();
var msgPrefix = code.charAt(0) + code.substring(1).toLowerCase();
var dProperties;
var iProperties;
var lineage;
if (_.isUndefined(schema.$ref)) {
processModel(spec, modelsMetadata, schema, toJsonPointer(sPath), sPath, results);
// The only checks we perform below are inheritance checks so skip all non-model definitions
if (['definitions', 'models'].indexOf(defProp) === -1) {
return;
}
metadata.parents.push(toJsonPointer(sPath));
} else {
if (!isRemoteRef(schema.$ref)) {
metadata.parents.push(refToJsonPointer(schema.$ref));
dProperties = [];
iProperties = [];
lineage = metadata.lineage;
getModelMetadata(modelsMetadata, refToJsonPointer(schema.$ref)).refs.push(sPath.concat('$ref'));
}
}
});
// Do not reprocess lineage if already processed
if (_.isUndefined(lineage)) {
lineage = [];
// Validate the default value against constraints
if (!_.isUndefined(model.default)) {
validateParameterConstraints(spec, model, model.defaultValue, path.concat('default'), results.errors);
}
walk(id, undefined, lineage);
// Skipping 'definitions' for now: https://github.com/reverb/swagger-spec/issues/127
// Root > next > ...
lineage.reverse();
// Keep track of model references in $ref, items.$ref
if (model.$ref) {
if (!isRemoteRef(model.$ref)) {
getModelMetadata(modelsMetadata, refToJsonPointer(model.$ref)).refs.push(path.concat(['$ref']));
}
} else if (model.type === 'array') {
validateArrayType(model, path, results.errors);
metadata.lineage = _.cloneDeep(lineage);
if (!_.isUndefined(model.items) && !_.isUndefined(model.items.$ref)) {
if (!isRemoteRef(model.items.$ref)) {
getModelMetadata(modelsMetadata,
refToJsonPointer(model.items.$ref)).refs.push(path.concat(['items', '$ref']));
}
} else if (!_.isUndefined(model.items) && !_.isUndefined(model.items.type) &&
spec.primitives.indexOf(model.items.type) === -1) {
_.each(model.items, function (item, index) {
var sPath = path.concat('items', index.toString());
metadata.cyclical = lineage.length > 1 && lineage[0] === id;
}
processModel(spec, modelsMetadata, item, toJsonPointer(sPath), sPath, results);
});
}
// Swagger 1.2 does not allow multiple inheritance while Swagger 2.0+ does
if (metadata.parents.length > 1 && swaggerVersion === '1.2') {
createErrorOrWarning('MULTIPLE_' + code + '_INHERITANCE',
'Child ' + code.toLowerCase() + ' is sub type of multiple models: ' +
_.map(metadata.parents, function (parent) {
return getDisplayId(parent);
}).join(' && '), defPath, results.errors);
}
_.each(model.properties, function (property, name) {
var pPath = path.concat('properties', name);
if (metadata.cyclical) {
createErrorOrWarning('CYCLICAL_' + code + '_INHERITANCE',
msgPrefix + ' has a circular inheritance: ' +
_.map(lineage, function (dep) {
return getDisplayId(dep);
}).join(' -> ') + ' -> ' + getDisplayId(id),
defPath.concat(swaggerVersion === '1.2' ? 'subTypes' : 'allOf'), results.errors);
}
// Keep track of model references in $ref, items.$ref
if (property.$ref) {
if (!isRemoteRef(property.$ref)) {
getModelMetadata(modelsMetadata, refToJsonPointer(property.$ref)).refs.push(pPath.concat(['$ref']));
// Remove self reference from the end of the lineage (Front too if cyclical)
_.each(lineage.slice(metadata.cyclical ? 1 : 0), function (id) {
var pModel = traverse(documentMetadata.resolved).get(JsonRefs.pathFromPointer(id));
_.each(Object.keys(pModel.properties), function (name) {
if (iProperties.indexOf(name) === -1) {
iProperties.push(name);
}
} else if (property.type === 'array') {
validateArrayType(property, pPath, results.errors);
});
});
if (!_.isUndefined(property.items) && !_.isUndefined(property.items.$ref) &&
!isRemoteRef(property.items.$ref)) {
getModelMetadata(modelsMetadata,
refToJsonPointer(property.items.$ref)).refs.push(pPath.concat(['items', '$ref']));
} else if (!_.isUndefined(property.items) && !_.isUndefined(property.items.type) &&
spec.primitives.indexOf(property.items.type) === -1) {
_.each(property.items, function (schema, index) {
var sPath = pPath.concat('items', index.toString());
// Validate simple definitions
validateSchemaConstraints(documentMetadata, definition, defPath, results);
processModel(spec, modelsMetadata, schema, toJsonPointer(sPath), sPath, results);
});
// Identify redeclared properties
_.each(definition.properties, function (property, name) {
var pPath = defPath.concat(['properties', name]);
// Do not process unresolved properties
if (!_.isUndefined(property)) {
validateSchemaConstraints(documentMetadata, property, pPath, results);
if (iProperties.indexOf(name) > -1) {
createErrorOrWarning('CHILD_' + code + '_REDECLARES_PROPERTY',
'Child ' + code.toLowerCase() + ' declares property already declared by ancestor: ' +
name,
pPath, results.errors);
} else {
dProperties.push(name);
}

@@ -517,656 +511,565 @@ }

// Add self reference to all model definitions outside of #/definitions (They are inline models or references)
if (path.length > 3 || toJsonPointer(path).indexOf('#/definitions/') === -1) {
metadata.refs.push(path);
// Identify missing required properties
_.each(definition.required || [], function (name, index) {
if (iProperties.indexOf(name) === -1 && dProperties.indexOf(name) === -1) {
createErrorOrWarning('MISSING_REQUIRED_MODEL_PROPERTY',
'Model requires property but it is not defined: ' + name,
defPath.concat(['required', index.toString()]), results.errors);
}
});
});
// Process references (Only processes JSON References, all other references are handled where encountered)
_.each(JsonRefs.findRefs(documentMetadata.original), function (ref, refPtr) {
if (documentMetadata.swaggerVersion === '1.2') {
ref = '#/models/' + ref;
}
break;
// Only process local references
if (!JsonRefs.isRemotePointer(ref)) {
addReference(documentMetadata, ref, refPtr, results);
}
});
};
var validateExist = function validateExist (data, val, codeSuffix, msgPrefix, path, dest) {
if (!_.isUndefined(data) && data.indexOf(val) === -1) {
createErrorOrWarning('UNRESOLVABLE_' + codeSuffix, msgPrefix + ' could not be resolved: ' + val, path, dest);
}
};
var getModelsMetadata = function getModelsMetadata (spec, apiDOrSO, results) {
var circular = {};
var localResults = {
errors: [],
warnings: []
};
var resolved = {};
var unresolved = {};
var addModelProps = function addModelProps (modelId, composed) {
var model = modelsMetadata[modelId].schema;
var processAuthRefs = function processAuthRefs (documentMetadata, authRefs, path, results) {
var code = documentMetadata.swaggerVersion === '1.2' ? 'AUTHORIZATION' : 'SECURITY_DEFINITION';
var msgPrefix = code === 'AUTHORIZATION' ? 'Authorization' : 'Security definition';
if (model) {
_.each(model.properties, function (prop, propName) {
var newProp = _.cloneDeep(prop);
if (documentMetadata.swaggerVersion === '1.2') {
_.reduce(authRefs, function (seenNames, scopes, name) {
var authPtr = '#/authorizations/' + name;
var aPath = path.concat([name]);
if (composed.properties[propName]) {
createErrorOrWarning('CHILD_MODEL_REDECLARES_PROPERTY',
'Child model declares property already declared by ancestor: ' + propName, prop,
spec.version === '1.2' ?
['models', modelId, 'properties', propName] :
modelId.substring(2).split('/').concat('properties', propName), localResults.errors);
} else {
if (spec.version === '1.2') {
// Sanitize the maximum/minimum values to be numbers
if (!_.isUndefined(newProp.maximum)) {
newProp.maximum = parseFloat(newProp.maximum);
}
// Add reference or record unresolved authorization
if (addReference(documentMetadata, authPtr, aPath, results)) {
_.reduce(scopes, function (seenScopes, scope, index) {
var sPath = aPath.concat(index.toString(), 'scope');
var sPtr = authPtr + '/scopes/' + scope.scope;
if (!_.isUndefined(newProp.minimum)) {
newProp.minimum = parseFloat(newProp.minimum);
}
}
composed.properties[propName] = newProp;
}
});
validateNoExist(seenScopes, scope.scope, code + '_SCOPE_REFERENCE', msgPrefix + ' scope reference', sPath,
results.warnings);
if (!_.isUndefined(model.required) && _.isUndefined(composed.required)) {
composed.required = [];
// Add reference or record unresolved authorization scope
addReference(documentMetadata, sPtr, sPath, results);
return seenScopes.concat(scope.scope);
}, []);
}
_.each(model.required, function (propName) {
if (composed.required.indexOf(propName) === -1) {
composed.required.push(propName);
return seenNames.concat(name);
}, []);
} else {
_.reduce(authRefs, function (seenNames, scopes, index) {
_.each(scopes, function (scopes, name) {
var authPtr = '#/securityDefinitions/' + name;
var authRefPath = path.concat(index.toString(), name);
// Ensure the security definition isn't referenced more than once (Swagger 2.0+)
validateNoExist(seenNames, name, code + '_REFERENCE', msgPrefix + ' reference', authRefPath,
results.warnings);
seenNames.push(name);
// Add reference or record unresolved authorization
if (addReference(documentMetadata, authPtr, authRefPath, results)) {
_.each(scopes, function (scope, index) {
// Add reference or record unresolved authorization scope
addReference(documentMetadata, authPtr + '/scopes/' + scope, authRefPath.concat(index.toString()),
results);
});
}
});
return seenNames;
}, []);
}
};
var resolveRefs = function (apiDOrSO, callback) {
var cacheEntry = getDocumentCache(apiDOrSO);
var swaggerVersion = helpers.getSwaggerVersion(apiDOrSO);
var documentT;
if (!cacheEntry.resolved) {
// For Swagger 1.2, we have to create real JSON References
if (swaggerVersion === '1.2') {
apiDOrSO = _.cloneDeep(apiDOrSO);
documentT = traverse(apiDOrSO);
_.each(JsonRefs.findRefs(apiDOrSO), function (ref, ptr) {
// All Swagger 1.2 references are ALWAYS to models
documentT.set(JsonRefs.pathFromPointer(ptr), '#/models/' + ref);
});
}
};
var getPath = function getPath (parent, unresolved) {
var parentVisited = false;
return Object.keys(unresolved).filter(function (dep) {
if (dep === parent) {
parentVisited = true;
// Resolve references
JsonRefs.resolveRefs(apiDOrSO, function (err, json) {
if (err) {
return callback(err);
}
return parentVisited && unresolved[dep];
cacheEntry.resolved = json;
cacheEntry.resolvedId = SparkMD5.hash(JSON.stringify(json));
callback();
});
};
var resolver = function resolver (modelId, circular, resolved, unresolved, composed) {
var metadata = modelsMetadata[modelId];
var model = metadata.schema;
} else {
callback();
}
};
unresolved[modelId] = true;
if (!_.isUndefined(model)) {
// 1.2 does not allow multiple inheritance while 2.0+ does
if (metadata.parents.length > 1 && spec.version === '1.2') {
createErrorOrWarning('MULTIPLE_MODEL_INHERITANCE',
'Child model is sub type of multiple models: ' + metadata.parents.join(' && '), model,
['models', modelId], localResults.errors);
var validateAgainstSchema = function validateAgainstSchema (spec, schemaOrName, data, callback) {
var validator = _.isString(schemaOrName) ? spec.validators[schemaOrName] : helpers.createJsonValidator();
var doValidation = function doValidation () {
try {
validators.validateAgainstSchema(schemaOrName, data, validator);
} catch (err) {
if (err.failedValidation) {
return callback(undefined, err.results);
} else {
_.each(metadata.parents, function (dep) {
if (!resolved[dep]) {
if (unresolved[dep]) {
circular[modelId] = getPath(dep, unresolved);
createErrorOrWarning('CYCLICAL_MODEL_INHERITANCE',
'Model has a circular inheritance: ' + modelId + ' -> ' +
circular[modelId].join(' -> '),
spec.version === '1.2' ?
model.subTypes :
model.allOf,
spec.version === '1.2' ?
['models', modelId, 'subTypes'] :
modelId.substring(2).split('/').concat('allOf'), localResults.errors);
}
// Do not resolve if circular
if (!circular[modelId]) {
resolver(dep, circular, resolved, unresolved, composed);
}
}
// Do not add properties if circular
if (!circular[modelId]) {
addModelProps(dep, composed);
}
});
return callback(err);
}
}
resolved[modelId] = true;
unresolved[modelId] = false;
resolveRefs(data, function (err) {
return callback(err);
});
};
var hash = md5.hash(JSON.stringify(apiDOrSO));
var metadataEntry = metadataCache[hash];
var modelsMetadata;
if (_.isUndefined(metadataEntry)) {
metadataEntry = metadataCache[hash] = {
metadata: {},
results: localResults
};
addExternalRefsToValidator(validator, data, function (err) {
if (err) {
return callback(err);
}
modelsMetadata = metadataEntry.metadata;
doValidation();
});
};
switch (spec.version) {
case '1.2':
_.reduce(apiDOrSO.models, function (seenModelIds, model, modelName) {
// Validate the model is not already defined (by id)
validateNoExist(seenModelIds, model.id, 'MODEL_DEFINITION', 'Model', ['models', modelName, 'id'],
localResults.errors);
var validateDefinitions = function validateDefinitions (documentMetadata, results) {
// Validate unused definitions
_.each(documentMetadata.definitions, function (metadata, id) {
var defPath = JsonRefs.pathFromPointer(id);
var defType = defPath[0].substring(0, defPath[0].length - 1);
var displayId = documentMetadata.swaggerVersion === '1.2' ? defPath[defPath.length - 1] : id;
var code = defType === 'securityDefinition' ? 'SECURITY_DEFINITION' : defType.toUpperCase();
var msgPrefix = defType === 'securityDefinition' ?
'Security definition' :
defType.charAt(0).toUpperCase() + defType.substring(1);
processModel(spec, modelsMetadata, model, model.id, ['models', modelName], localResults);
if (metadata.references.length === 0) {
// Swagger 1.2 authorization scope
if (metadata.scopePath) {
code += '_SCOPE';
msgPrefix += ' scope';
defPath = metadata.scopePath;
}
return seenModelIds.concat(model.id);
}, []);
createUnusedErrorOrWarning(displayId, code, msgPrefix, defPath, results.warnings);
}
});
};
break;
var validateParameters = function validateParameters (spec, documentMetadata, nPath, parameters, path, results,
skipMissing) {
var pathParams = [];
case '2.0':
// Find models defined/referenced in #/definitions
_.each(apiDOrSO.definitions, function (model, modelId) {
var dPath = ['definitions', modelId];
_.reduce(parameters, function (seenParameters, parameter, index) {
var pPath = path.concat(['parameters', index.toString()]);
processModel(spec, modelsMetadata, model, toJsonPointer(dPath), dPath, localResults);
});
break;
// Unresolved parameter
if (_.isUndefined(parameter)) {
return;
}
// Compose models and identify inheritance issues
_.each(modelsMetadata, function (metadata, modelId) {
metadata.composed = {
title: 'Composed ' + modelId,
type: 'object',
properties: {}
};
// Identify duplicate parameter names
validateNoExist(seenParameters, parameter.name, 'PARAMETER', 'Parameter', pPath.concat('name'),
results.errors);
if (!_.isUndefined(metadata.schema)) {
resolver(modelId, circular, resolved, unresolved, metadata.composed);
addModelProps(modelId, metadata.composed);
// Keep track of path parameters
if (parameter.paramType === 'path' || parameter.in === 'path') {
if (nPath.args.indexOf(parameter.name) === -1) {
createErrorOrWarning('UNRESOLVABLE_API_PATH_PARAMETER',
'API path parameter could not be resolved: ' + parameter.name, pPath.concat('name'),
results.errors);
}
// Validate required properties
if (!_.isUndefined(metadata.schema) && !_.isUndefined(metadata.schema.required)) {
_.each(metadata.schema.required, function (propName, index) {
if (_.isUndefined(metadata.composed.properties[propName])) {
createErrorOrWarning('MISSING_REQUIRED_MODEL_PROPERTY',
'Model requires property but it is not defined: ' + propName, propName,
metadata.path.concat(['required', index.toString()]), results.errors);
}
});
}
});
pathParams.push(parameter.name);
}
// Resolve references
_.each(modelsMetadata, function (metadata) {
var refs = traverse(metadata.composed).reduce(function (acc) {
if (this.key === '$ref') {
acc[toJsonPointer(this.path)] = spec.version === '1.2' ? this.node : refToJsonPointer(this.node);
}
// Validate parameter constraints
validateSchemaConstraints(documentMetadata, parameter, pPath, results, parameter.skipErrors);
return acc;
}, {});
return seenParameters.concat(parameter.name);
}, []);
_.each(refs, function (modelId, pathPtr) {
var path = pathPtr.substring(2).split('/');
var refModel = _.isUndefined(modelsMetadata[modelId]) ?
undefined :
_.cloneDeep(modelsMetadata[modelId].composed);
if (!_.isUndefined(refModel)) {
delete refModel.id;
delete refModel.title;
traverse(metadata.composed).set(path.slice(0, path.length - 1), refModel);
}
});
// Validate missing path parameters (in path but not in operation.parameters)
if (_.isUndefined(skipMissing) || skipMissing === false) {
_.each(_.difference(nPath.args, pathParams), function (unused) {
createErrorOrWarning('MISSING_API_PATH_PARAMETER', 'API requires path parameter but it is not defined: ' + unused,
documentMetadata.swaggerVersion === '1.2' ? path.slice(0, 2).concat('path') : path,
results.errors);
});
// Merge results
if (!_.isUndefined(results)) {
_.each(localResults, function (entries, destName) {
results[destName] = results[destName].concat(entries);
});
}
}
return metadataEntry;
};
var validateWithSchema = function validateWithSchema (spec, schemaName, data) {
var validator = spec.validators[schemaName];
var schema = validator.schema[schemaName];
var result = validator.validate(schema, data);
var response = {
var validateSwagger1_2 = function validateSwagger1_2 (spec, resourceListing, apiDeclarations, callback) { // jshint ignore:line
var adResourcePaths = [];
var rlDocumentMetadata = getDocumentCache(resourceListing);
var rlResourcePaths = [];
var results = {
errors: [],
warnings: []
warnings: [],
apiDeclarations: []
};
if (result) {
response = {
errors: validator.je(schema, data, result, jjveOptions),
warnings: []
};
}
// Process Resource Listing resource definitions
rlResourcePaths = _.reduce(resourceListing.apis, function (seenPaths, api, index) {
// Identify duplicate resource paths defined in the Resource Listing
validateNoExist(seenPaths, api.path, 'RESOURCE_PATH', 'Resource path', ['apis', index.toString(), 'path'],
results.errors);
return response;
};
seenPaths.push(api.path);
var validateContent = function validateContent (spec, rlOrSO, apiDeclarations) {
var response = {
errors: [],
warnings: []
};
var authDefs = {}; // (1.2)
var authRefs = {}; // (1.2)
var pathDefs = []; // (1.2)
var pathRefs = []; // (1.2)
return seenPaths;
}, []);
switch (spec.version) {
case '1.2':
// Build path model
_.each(rlOrSO.apis, function (api, index) {
// Validate duplicate resource paths
validateNoExist(pathDefs, api.path, 'RESOURCE_PATH', 'Resource path', ['apis', index.toString(), 'path'],
response.errors);
// Process Resource Listing definitions (authorizations)
processDocument(rlDocumentMetadata, results);
if (pathDefs.indexOf(api.path) === -1) {
pathDefs.push(api.path);
}
});
if (response.errors.length === 0) {
// Build the authorization model
_.each(rlOrSO.authorizations, function (authorization, name) {
authDefs[name] = _.map(authorization.scopes, function (scope) {
return scope.scope;
});
}, {});
// Process each API Declaration
adResourcePaths = _.reduce(apiDeclarations, function (seenResourcePaths, apiDeclaration, index) {
var aResults = results.apiDeclarations[index] = {
errors: [],
warnings: []
};
var adDocumentMetadata = getDocumentCache(apiDeclaration);
response.apiDeclarations = [];
// Identify duplicate resource paths defined in the API Declarations
validateNoExist(seenResourcePaths, apiDeclaration.resourcePath, 'RESOURCE_PATH', 'Resource path',
['resourcePath'], aResults.errors);
// Validate the API declarations
_.each(apiDeclarations, function (apiDeclaration, index) {
var result = response.apiDeclarations[index] = {
errors: [],
warnings: []
};
var apiAuthDefs = {};
var apiAuthRefs = {};
var modelsMetadata = getModelsMetadata(spec, apiDeclaration, result).metadata;
var addModelRef = function addModelRef (modelId, modelRef) {
var metadata = getModelMetadata(modelsMetadata, modelId);
if (adResourcePaths.indexOf(apiDeclaration.resourcePath) === -1) {
// Identify unused resource paths defined in the API Declarations
validateExist(rlResourcePaths, apiDeclaration.resourcePath, 'RESOURCE_PATH', 'Resource path',
['resourcePath'], aResults.errors);
metadata.refs.push(modelRef);
};
var addScopeRef = function addScopeRef (authId, scopeId) {
var auth;
seenResourcePaths.push(apiDeclaration.resourcePath);
}
if (!_.isUndefined(apiAuthDefs[authId])) {
// Local auth definition
auth = apiAuthRefs[authId];
// TODO: Process authorization references
// Not possible due to https://github.com/swagger-api/swagger-spec/issues/159
if (_.isUndefined(auth)) {
auth = apiAuthRefs[authId] = [];
}
} else {
// Global (Or missing in which case we'll assume global)
auth = authRefs[authId];
// Process models
processDocument(adDocumentMetadata, aResults);
if (_.isUndefined(auth)) {
auth = authRefs[authId] = [];
}
}
// Process the API definitions
_.reduce(apiDeclaration.apis, function (seenPaths, api, index) {
var aPath = ['apis', index.toString()];
var nPath = normalizePath(api.path);
if (auth.indexOf(scopeId) === -1) {
auth.push(scopeId);
}
};
// Validate duplicate resource path
if (seenPaths.indexOf(nPath.path) > -1) {
createErrorOrWarning('DUPLICATE_API_PATH', 'API path (or equivalent) already defined: ' + api.path,
aPath.concat('path'), aResults.errors);
} else {
seenPaths.push(nPath.path);
}
// Build the authorization model
_.each(apiDeclaration.authorizations, function (authorization, name) {
apiAuthDefs[name] = _.map(authorization.scopes, function (scope) {
return scope.scope;
});
}, {});
// Process the API operations
_.reduce(api.operations, function (seenMethods, operation, index) {
var oPath = aPath.concat(['operations', index.toString()]);
// Validate duplicate resource path
validateNoExist(pathRefs, apiDeclaration.resourcePath, 'RESOURCE_PATH', 'Resource path', ['resourcePath'],
result.errors);
// Validate duplicate operation method
validateNoExist(seenMethods, operation.method, 'OPERATION_METHOD', 'Operation method', oPath.concat('method'),
aResults.errors);
// Validate missing resource path definition
validateExist(pathDefs, apiDeclaration.resourcePath, 'RESOURCE_PATH', 'Resource path', ['resourcePath'],
result.errors);
// Keep track of the seen methods
seenMethods.push(operation.method);
// Keep track of the seen paths
if (pathRefs.indexOf(apiDeclaration.resourcePath) === -1) {
pathRefs.push(apiDeclaration.resourcePath);
// Keep track of operation types
if (spec.primitives.indexOf(operation.type) === -1 && spec.version === '1.2') {
addReference(adDocumentMetadata, '#/models/' + operation.type, oPath.concat('type'), aResults);
}
// Validate consumes/produces uniqueness
_.each(['consumes', 'produces'], function (name) {
validateNoDuplicates(apiDeclaration[name], 'API_' + name.toUpperCase(), 'API', [name],
result.warnings);
});
// Process authorization references
processAuthRefs(rlDocumentMetadata, operation.authorizations, oPath.concat('authorizations'), aResults);
// Valdate APIs
_.reduce(apiDeclaration.apis, function (seenApiPaths, api, index) {
var aPath = ['apis', index.toString()];
var nPath = normalizePath(api.path);
var sParams = [];
// Validate validate inline constraints
validateSchemaConstraints(adDocumentMetadata, operation, oPath, aResults);
// Validate duplicate resource path
if (seenApiPaths.indexOf(nPath.path) > -1) {
createErrorOrWarning('DUPLICATE_API_PATH', 'API path (or equivalent) already defined: ' + api.path,
api.path, aPath.concat('path'), result.errors);
}
// Validate parameters
validateParameters(spec, adDocumentMetadata, nPath, operation.parameters, oPath, aResults);
// Validate operations
_.reduce(api.operations, function (seenMethods, operation, index) {
var oPath = aPath.concat(['operations', index.toString()]);
// Validate unique response code
_.reduce(operation.responseMessages, function (seenResponseCodes, responseMessage, index) {
var rmPath = oPath.concat(['responseMessages', index.toString()]);
// Validate consumes/produces uniqueness
_.each(['consumes', 'produces'], function (name) {
validateNoDuplicates(operation[name], 'OPERATION_' + name.toUpperCase(), 'Operation',
oPath.concat(name), result.warnings);
});
validateNoExist(seenResponseCodes, responseMessage.code, 'RESPONSE_MESSAGE_CODE', 'Response message code',
rmPath.concat(['code']), aResults.errors);
// Validate unique method
validateNoExist(seenMethods, operation.method, 'OPERATION_METHOD', 'Operation method',
oPath.concat('method'), result.errors);
// Validate missing model
if (responseMessage.responseModel) {
addReference(adDocumentMetadata, '#/models/' + responseMessage.responseModel,
rmPath.concat('responseModel'), aResults);
}
// Validate authorizations
_.each(operation.authorizations, function (scopes, name) {
// Validate missing authorization
validateExist(_.uniq(Object.keys(apiAuthDefs).concat(Object.keys(authDefs))), name, 'AUTHORIZATION',
'Authorization', oPath.concat(['authorizations', name]), result.errors);
return seenResponseCodes.concat(responseMessage.code);
}, []);
// Validate missing authorization scopes (Only when the authorization is not missing)
_.each(scopes, function (scope, index) {
if (!_.isUndefined(apiAuthDefs[name]) || !_.isUndefined(authDefs[name])) {
// Validate missing authorization scope
validateExist(_.uniq((apiAuthDefs[name] || []).concat(authDefs[name] || [])), scope.scope,
'AUTHORIZATION_SCOPE', 'Authorization scope',
oPath.concat(['authorizations', name, index.toString(), 'scope']), result.errors);
}
return seenMethods;
}, []);
addScopeRef(name, scope.scope);
});
});
return seenPaths;
}, []);
// Validate parameters
_.reduce(operation.parameters, function (seenParameters, parameter, index) {
var pPath = oPath.concat('parameters', index.toString());
// Validate API Declaration definitions
validateDefinitions(adDocumentMetadata, aResults);
validateArrayType(parameter, pPath, result.errors);
return seenResourcePaths;
}, []);
// Add model references from parameter type/items
if (spec.primitives.indexOf(parameter.type) === -1) {
addModelRef(parameter.type, oPath.concat(['parameters', index.toString(), 'type']));
} else if (parameter.type === 'array' && !_.isUndefined(parameter.items) &&
!_.isUndefined(parameter.items.$ref)) {
addModelRef(parameter.items.$ref, pPath.concat(['items', '$ref']));
}
// Validate API Declaration definitions
validateDefinitions(rlDocumentMetadata, results);
// Validate duplicate parameter name
validateNoExist(seenParameters, parameter.name, 'OPERATION_PARAMETER', 'Operation parameter',
pPath.concat('name'), result.errors);
// Identify unused resource paths defined in the Resource Listing
_.each(_.difference(rlResourcePaths, adResourcePaths), function (unused) {
var index = rlResourcePaths.indexOf(unused);
// Keep track of path parameters
if (parameter.paramType === 'path') {
if (nPath.args.indexOf(parameter.name) === -1) {
createErrorOrWarning('UNRESOLVABLE_API_PATH_PARAMETER',
'API path parameter could not be resolved: ' + parameter.name, parameter.name,
pPath.concat('name'), result.errors);
}
createUnusedErrorOrWarning(resourceListing.apis[index].path, 'RESOURCE_PATH', 'Resource path',
['apis', index.toString(), 'path'], results.errors);
});
if (sParams.indexOf(parameter.name) === -1) {
sParams.push(parameter.name);
}
}
callback(undefined, results);
};
if (!_.isUndefined(parameter.defaultValue)) {
// Validate default value against constraints
validateParameterConstraints(spec, parameter, parameter.defaultValue,
oPath.concat('parameters', index.toString(), 'defaultValue'),
result.errors);
}
var validateSwagger2_0 = function validateSwagger2_0 (spec, swaggerObject, callback) { // jshint ignore:line
var documentMetadata = getDocumentCache(swaggerObject);
var results = {
errors: [],
warnings: []
};
return seenParameters.concat(parameter.name);
}, []);
// Process definitions
processDocument(documentMetadata, results);
// Validate missing path parameters (in path but not in operation.parameters)
_.each(_.difference(nPath.args, sParams), function (unused) {
createErrorOrWarning('MISSING_API_PATH_PARAMETER',
'API requires path parameter but it is not defined: ' + unused, api.path,
aPath.concat('path'), result.errors);
});
// Process security references
processAuthRefs(documentMetadata, swaggerObject.security, ['security'], results);
// Validate unique response code
_.reduce(operation.responseMessages, function (seenResponseCodes, responseMessage, index) {
validateNoExist(seenResponseCodes, responseMessage.code, 'RESPONSE_MESSAGE_CODE', 'Response message code',
oPath.concat(['responseMessages', index.toString(), 'code']), result.errors);
_.reduce(documentMetadata.resolved.paths, function (seenPaths, path, name) {
var pPath = ['paths', name];
var nPath = normalizePath(name);
// Add model references from responseMessages responseModel
if (responseMessage.responseModel) {
addModelRef(responseMessage.responseModel,
oPath.concat(['responseMessages', index.toString(), 'responseModel']));
}
// Validate duplicate resource path
if (seenPaths.indexOf(nPath.path) > -1) {
createErrorOrWarning('DUPLICATE_API_PATH', 'API path (or equivalent) already defined: ' + name, pPath,
results.errors);
}
return seenResponseCodes.concat(responseMessage.code);
}, []);
// Validate parameters
validateParameters(spec, documentMetadata, nPath, path.parameters, pPath, results, true);
validateArrayType(operation, oPath, result.errors);
// Validate the Operations
_.each(path, function (operation, method) {
var cParams = [];
var oPath = pPath.concat(method);
var seenParams = [];
// Add model references from type/items
if (operation.type === 'array' && !_.isUndefined(operation.items) && !_.isUndefined(operation.items.$ref)) {
addModelRef(operation.items.$ref, oPath.concat(['items', '$ref']));
} else if (spec.primitives.indexOf(operation.type) === -1) {
addModelRef(operation.type, oPath.concat(['type']));
}
if (method === 'parameters') {
return;
}
return seenMethods.concat(operation.method);
}, []);
// Process security references
processAuthRefs(documentMetadata, operation.security, oPath.concat('security'), results);
return seenApiPaths.concat(nPath.path);
}, []);
// Compose parameters from path global parameters and operation parameters
_.each(operation.parameters, function (parameter) {
cParams.push(parameter);
// Validate models
_.each(modelsMetadata, function (metadata, modelId) {
// Identify missing models (referenced but not declared)
if (_.isUndefined(metadata.schema)) {
_.each(metadata.refs, function (ref) {
createErrorOrWarning('UNRESOLVABLE_MODEL', 'Model could not be resolved: ' + modelId,
modelId, ref, result.errors);
});
}
// Identify unused models (declared but not referenced)
if (metadata.refs.length === 0) {
createUnusedErrorOrWarning(metadata.schema, modelId, 'MODEL', 'Model', ['models', metadata.name],
result.warnings);
}
});
// Validate unused authorizations
_.each(_.difference(Object.keys(apiAuthDefs), Object.keys(apiAuthRefs)), function (unused) {
createUnusedErrorOrWarning(apiDeclaration.authorizations[unused], unused, 'AUTHORIZATION', 'Authorization',
['authorizations', unused], result.warnings);
});
// Validate unused authorization scopes
_.each(apiAuthDefs, function (scopes, name) {
var path = ['authorizations', name];
var authDef = apiDeclaration.authorizations[name];
_.each(_.difference(scopes, apiAuthRefs[name] || []), function (scope) {
var sIndex = scopes.indexOf(scope);
createUnusedErrorOrWarning(authDef.scopes[sIndex], scope, 'AUTHORIZATION_SCOPE',
'Authorization scope', path.concat(['scopes', sIndex.toString()]),
result.warnings);
});
});
seenParams.push(parameter.name + ':' + parameter.in);
});
// Validate unused resources
_.each(_.difference(pathDefs, pathRefs), function (unused) {
var index = _.map(rlOrSO.apis, function (api) { return api.path; }).indexOf(unused);
_.each(path.parameters, function (parameter) {
var cloned = _.cloneDeep(parameter);
createUnusedErrorOrWarning(rlOrSO.apis[index].path, unused, 'RESOURCE_PATH', 'Resource path',
['apis', index.toString(), 'path'], response.errors);
});
// The only errors that can occur here are schema constraint validation errors which are already reported above
// so do not report them again.
cloned.skipErrors = true;
// Validate unused authorizations
_.each(_.difference(Object.keys(authDefs), Object.keys(authRefs)), function (unused) {
createUnusedErrorOrWarning(rlOrSO.authorizations[unused], unused, 'AUTHORIZATION', 'Authorization',
['authorizations', unused], response.warnings);
if (seenParams.indexOf(parameter.name + ':' + parameter.in) === -1) {
cParams.push(cloned);
}
});
// Validate unused authorization scopes
_.each(authRefs, function (scopes, name) {
var path = ['authorizations', name];
// Validate parameters
validateParameters(spec, documentMetadata, nPath, cParams, oPath, results);
_.each(_.difference(scopes, authRefs[name]), function (unused) {
var index = scopes.indexOf(unused);
createUnusedErrorOrWarning(rlOrSO.authorizations[name].scopes[index], unused, 'AUTHORIZATION_SCOPE',
'Authorization scope', path.concat(['scopes', index.toString()]),
response.warnings);
});
// Validate responses
_.each(operation.responses, function (response, responseCode) {
// Validate validate inline constraints
validateSchemaConstraints(documentMetadata, response, oPath.concat('responses', responseCode), results);
});
}
break;
case '2.0':
// Validate (for now) unique consumes/produces/schemes
_.each(['consumes', 'produces', 'schemes'], function (name) {
validateNoDuplicates(rlOrSO[name], 'API_' + name.toUpperCase(), 'API', [name], response.warnings);
});
if (response.errors.length === 0 && response.warnings.length === 0) {
var modelsMetadata = getModelsMetadata(spec, rlOrSO, response).metadata;
return seenPaths.concat(nPath.path);
}, []);
// Validate the Paths
_.reduce(rlOrSO.paths, function (seenPaths, path, name) {
var aPath = ['paths', name];
var nPath = normalizePath(name);
var sParams = [];
// Validate definitions
validateDefinitions(documentMetadata, results);
// Validate duplicate resource path
if (seenPaths.indexOf(nPath.path) > -1) {
createErrorOrWarning('DUPLICATE_API_PATH', 'API path (or equivalent) already defined: ' + name,
name, aPath, response.errors);
}
callback(undefined, results);
};
// Validate the Operations
_.each(path, function (operation, method) {
var oPath = aPath.concat(method);
var validateSemantically = function validateSemantically (spec, rlOrSO, apiDeclarations, callback) {
var cbWrapper = function cbWrapper (err, results) {
callback(err, helpers.formatResults(results));
};
if (spec.version === '1.2') {
validateSwagger1_2(spec, rlOrSO, apiDeclarations, cbWrapper); // jshint ignore:line
} else {
validateSwagger2_0(spec, rlOrSO, cbWrapper); // jshint ignore:line
}
};
if (method === 'parameters') {
// Validate parameter constraints
_.reduce(path.parameters, function (seenParameters, parameter, index) {
var pPath = oPath.concat(index.toString());
var validateStructurally = function validateStructurally (spec, rlOrSO, apiDeclarations, callback) {
validateAgainstSchema(spec, spec.version === '1.2' ? 'resourceListing.json' : 'schema.json', rlOrSO,
function (err, results) {
if (err) {
return callback(err);
}
// Validate duplicate parameter name
validateNoExist(seenParameters, parameter.name, 'API_PARAMETER', 'API parameter',
pPath.concat('name'), response.errors);
// Only validate the API Declarations if the API is 1.2 and the Resource Listing was valid
if (!results && spec.version === '1.2') {
results = {
errors: [],
warnings: [],
apiDeclarations: []
};
// Keep track of path parameters
if (parameter.in === 'path') {
if (nPath.args.indexOf(parameter.name) === -1) {
createErrorOrWarning('UNRESOLVABLE_API_PATH_PARAMETER',
'API path parameter could not be resolved: ' + parameter.name, parameter.name,
pPath.concat('name'), response.errors);
}
async.map(apiDeclarations, function (apiDeclaration, callback) {
validateAgainstSchema(spec, 'apiDeclaration.json', apiDeclaration, callback);
}, function (err, allResults) {
if (err) {
return callback(err);
}
if (sParams.indexOf(parameter.name) === -1) {
sParams.push(parameter.name);
}
}
_.each(allResults, function (result, index) {
results.apiDeclarations[index] = result;
});
// Find models defined/referenced in #/paths/{path}/parameters
if (!_.isUndefined(parameter.schema)) {
processModel(spec, modelsMetadata, parameter.schema, toJsonPointer(pPath.concat('schema')),
pPath.concat('schema'), response);
}
callback(undefined, results);
});
} else {
callback(undefined, results);
}
});
};
return seenParameters.concat(parameter.name);
}, []);
/**
* Callback used by all json-refs functions.
*
* @param {error} [err] - The error if there is a problem
* @param {*} [result] - The result of the function
*
* @callback resultCallback
*/
return;
}
/**
* Creates a new Swagger specification object.
*
* @param {string} version - The Swagger version
*
* @constructor
*/
var Specification = function Specification (version) {
var createValidators = function createValidators (spec, validatorsMap) {
return _.reduce(validatorsMap, function (result, schemas, schemaName) {
result[schemaName] = helpers.createJsonValidator(schemas);
// Validate (for now) consumes/produces/schemes uniqueness
_.each(['consumes', 'produces', 'schemes'], function (name) {
validateNoDuplicates(operation[name], 'OPERATION_' + name.toUpperCase(), 'Operation',
oPath.concat(name), response.warnings);
});
return result;
}.bind(this), {});
};
var fixSchemaId = function fixSchemaId (schemaName) {
// Swagger 1.2 schema files use one id but use a different id when referencing schema files. We also use the schema
// file name to reference the schema in ZSchema. To fix this so that the JSON Schema validator works properly, we
// need to set the id to be the name of the schema file.
var fixed = _.cloneDeep(this.schemas[schemaName]);
// Validate parameter constraints
_.reduce(operation.parameters, function (seenParameters, parameter, index) {
var pPath = oPath.concat('parameters', index.toString());
fixed.id = schemaName;
// Validate duplicate parameter name
validateNoExist(seenParameters, parameter.name, 'OPERATION_PARAMETER', 'Operation parameter',
pPath.concat('name'), response.errors);
return fixed;
}.bind(this);
var primitives = ['string', 'number', 'boolean', 'integer', 'array'];
// Keep track of path parameters
if (parameter.in === 'path') {
if (nPath.args.indexOf(parameter.name) === -1) {
createErrorOrWarning('UNRESOLVABLE_API_PATH_PARAMETER',
'API path parameter could not be resolved: ' + parameter.name, parameter.name,
pPath.concat('name'), response.errors);
}
switch (version) {
case '1.2':
this.docsUrl = 'https://github.com/swagger-api/swagger-spec/blob/master/versions/1.2.md';
this.primitives = _.union(primitives, ['void', 'File']);
this.schemasUrl = 'https://github.com/swagger-api/swagger-spec/tree/master/schemas/v1.2';
if (sParams.indexOf(parameter.name) === -1) {
sParams.push(parameter.name);
}
}
// Here explicitly to allow browserify to work
this.schemas = {
'apiDeclaration.json': require('../schemas/1.2/apiDeclaration.json'),
'authorizationObject.json': require('../schemas/1.2/authorizationObject.json'),
'dataType.json': require('../schemas/1.2/dataType.json'),
'dataTypeBase.json': require('../schemas/1.2/dataTypeBase.json'),
'infoObject.json': require('../schemas/1.2/infoObject.json'),
'modelsObject.json': require('../schemas/1.2/modelsObject.json'),
'oauth2GrantType.json': require('../schemas/1.2/oauth2GrantType.json'),
'operationObject.json': require('../schemas/1.2/operationObject.json'),
'parameterObject.json': require('../schemas/1.2/parameterObject.json'),
'resourceListing.json': require('../schemas/1.2/resourceListing.json'),
'resourceObject.json': require('../schemas/1.2/resourceObject.json')
};
// Find models defined/referenced in #/paths/{path}/{method}/parameters
if (!_.isUndefined(parameter.schema)) {
processModel(spec, modelsMetadata, parameter.schema, toJsonPointer(pPath.concat('schema')),
pPath.concat('schema'), response);
}
this.validators = createValidators(this, {
'apiDeclaration.json': _.map([
'dataTypeBase.json',
'modelsObject.json',
'oauth2GrantType.json',
'authorizationObject.json',
'parameterObject.json',
'operationObject.json',
'apiDeclaration.json'
], fixSchemaId),
'resourceListing.json': _.map([
'resourceObject.json',
'infoObject.json',
'oauth2GrantType.json',
'authorizationObject.json',
'resourceListing.json'
], fixSchemaId)
});
return seenParameters.concat(parameter.name);
}, []);
break;
// Find models defined/referenced in #/paths/{path}/{method}/responses
_.each(operation.responses, function (responseObj, responseCode) {
var rPath = oPath.concat('responses', responseCode);
case '2.0':
this.docsUrl = 'https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md';
this.primitives = _.union(primitives, ['file']);
this.schemasUrl = 'https://github.com/swagger-api/swagger-spec/tree/master/schemas/v2.0';
if (!_.isUndefined(responseObj.schema)) {
processModel(spec, modelsMetadata, responseObj.schema, toJsonPointer(rPath.concat('schema')),
rPath.concat('schema'), response);
}
});
});
// Here explicitly to allow browserify to work
this.schemas = {
'schema.json': require('../schemas/2.0/schema.json')
};
// Validate missing path parameters (in path but not in operation.parameters)
_.each(_.difference(nPath.args, sParams), function (unused) {
createErrorOrWarning('MISSING_API_PATH_PARAMETER',
'API requires path parameter but it is not defined: ' + unused, name,
aPath, response.errors);
});
this.validators = createValidators(this, {
'schema.json': [fixSchemaId('schema.json')]
});
return seenPaths.concat(nPath.path);
}, []);
break;
// Validate models
_.each(modelsMetadata, function (metadata, modelId) {
// Identify missing models (referenced but not declared)
if (_.isUndefined(metadata.schema)) {
_.each(metadata.refs, function (ref) {
createErrorOrWarning('UNRESOLVABLE_MODEL', 'Model could not be resolved: ' + modelId, modelId, ref,
response.errors);
});
}
// Identify unused models (declared but not referenced)
if (metadata.refs.length === 0) {
createUnusedErrorOrWarning(metadata.schema, modelId, 'MODEL', 'Model', modelId.substring(2).split('/'),
response.warnings);
}
});
}
break;
default:
throw new Error(version + ' is an unsupported Swagger specification version');
}
return response;
this.version = version;
};

@@ -1179,12 +1082,9 @@

* @param {object[]} [apiDeclarations] - The array of Swagger API Declarations (1.2)
* @param {resultCallback} callback - The result callback
*
* @returns undefined if validation passes or an object containing errors and/or warnings
* @throws Error if the arguments provided are not valid
*/
Specification.prototype.validate = function validate (rlOrSO, apiDeclarations) {
var response = {
errors: [],
warnings: []
};
var skipRemaining = false;
Specification.prototype.validate = function validate (rlOrSO, apiDeclarations, callback) {
// Validate arguments
switch (this.version) {

@@ -1205,37 +1105,94 @@ case '1.2':

// Validate structurally
response = validateWithSchema(this, 'resourceListing.json', rlOrSO);
break;
if (response.errors.length > 0) {
skipRemaining = true;
case '2.0':
// Validate arguments
if (_.isUndefined(rlOrSO)) {
throw new Error('swaggerObject is required');
} else if (!_.isPlainObject(rlOrSO)) {
throw new TypeError('swaggerObject must be an object');
}
if (!skipRemaining) {
response.apiDeclarations = [];
break;
}
_.each(apiDeclarations, function (apiDeclaration, index) {
response.apiDeclarations[index] = validateWithSchema(this, 'apiDeclaration.json', apiDeclaration);
if (this.version === '2.0') {
callback = arguments[1];
}
if (response.apiDeclarations[index].errors.length > 0) {
skipRemaining = true;
if (_.isUndefined(callback)) {
throw new Error('callback is required');
} else if (!_.isFunction(callback)) {
throw new TypeError('callback must be a function');
}
// Skip the remaining validation
return false;
}
}.bind(this));
// For Swagger 2.0, make sure apiDeclarations is an empty array
if (this.version === '2.0') {
apiDeclarations = [];
}
// Perform the validation
validateStructurally(this, rlOrSO, apiDeclarations, function (err, result) {
if (err || helpers.formatResults(result)) {
callback(err, result);
} else {
validateSemantically(this, rlOrSO, apiDeclarations, callback);
}
}.bind(this));
};
// Validate semantically
if (!skipRemaining) {
response = validateContent(this, rlOrSO, apiDeclarations);
/**
* Returns a JSON Schema representation of a composed model based on its id or reference.
*
* @param {object} apiDOrSO - The Swagger Resource API Declaration (1.2) or the Swagger Object (2.0)
* @param {string} modelIdOrRef - The model id (1.2) or the reference to the model (1.2 or 2.0)
* @param {resultCallback} callback - The result callback
*
* @returns the object representing a composed object
*
* @throws Error if there are validation errors while creating
*/
Specification.prototype.composeModel = function composeModel (apiDOrSO, modelIdOrRef, callback) {
var swaggerVersion = helpers.getSwaggerVersion(apiDOrSO);
var doComposition = function doComposition (err, results) {
var documentMetadata;
if (err) {
return callback(err);
} else if (helpers.formatResults(results)) {
return handleValidationError(results, callback);
}
// Set the response
response = response.errors.length > 0 || response.warnings.length > 0 ||
_.reduce(response.apiDeclarations, function (count, apiDeclaration) {
return count +
(_.isArray(apiDeclaration.errors) ? apiDeclaration.errors.length : 0) +
(_.isArray(apiDeclaration.warnings) ? apiDeclaration.warnings.length : 0);
}, 0) > 0 ? response : undefined;
documentMetadata = getDocumentCache(apiDOrSO);
results = {
errors: [],
warnings: []
};
processDocument(documentMetadata, results);
if (!documentMetadata.definitions[modelIdOrRef]) {
return callback();
}
if (helpers.formatResults(results)) {
return handleValidationError(results, callback);
}
callback(undefined, getOrComposeSchema(documentMetadata, modelIdOrRef));
};
switch (this.version) {
case '1.2':
// Validate arguments
if (_.isUndefined(apiDOrSO)) {
throw new Error('apiDeclaration is required');
} else if (!_.isPlainObject(apiDOrSO)) {
throw new TypeError('apiDeclaration must be an object');
}
if (_.isUndefined(modelIdOrRef)) {
throw new Error('modelId is required');
}
break;

@@ -1245,45 +1202,47 @@

// Validate arguments
if (_.isUndefined(rlOrSO)) {
if (_.isUndefined(apiDOrSO)) {
throw new Error('swaggerObject is required');
} else if (!_.isPlainObject(rlOrSO)) {
} else if (!_.isPlainObject(apiDOrSO)) {
throw new TypeError('swaggerObject must be an object');
}
// Validate structurally
response = validateWithSchema(this, 'schema.json', rlOrSO);
if (response.errors.length > 0) {
skipRemaining = true;
if (_.isUndefined(modelIdOrRef)) {
throw new Error('modelRef is required');
}
// Validate semantically
if (!skipRemaining) {
response = validateContent(this, rlOrSO);
}
break;
}
// Set the response
response = response.errors.length > 0 || response.warnings.length > 0 ? response : undefined;
if (_.isUndefined(callback)) {
throw new Error('callback is required');
} else if (!_.isFunction(callback)) {
throw new TypeError('callback must be a function');
}
break;
if (modelIdOrRef.charAt(0) !== '#') {
if (this.version === '1.2') {
modelIdOrRef = '#/models/' + modelIdOrRef;
} else {
throw new Error('modelRef must be a JSON Pointer');
}
}
return response;
// Ensure the document is valid first
validateAgainstSchema(this, swaggerVersion === '1.2' ? 'apiDeclaration.json' : 'schema.json', apiDOrSO,
doComposition);
};
/**
* Returns a JSON Schema representation of a composed model based on its id.
* Validates a model based on its id.
*
* @param {object} apiDOrSO - The Swagger Resource API Declaration (1.2) or the Swagger Object (2.0)
* @param {string} modelIdOrPath - The model id (1.2 or 2.0) or the path to the model (2.0)
* @param {string} modelIdOrRef - The model id (1.2) or the reference to the model (1.2 or 2.0)
* @param {object} data - The model to validate
* @param {resultCallback} callback - The result callback
*
* @returns the object representing a composed object
* @returns undefined if validation passes or an object containing errors and/or warnings
*
* @throws Error if there are validation errors while creating
*/
Specification.prototype.composeModel = function composeModel (apiDOrSO, modelIdOrPath) {
var metadataEntry;
var modelMetadata;
var modelsMetadata;
var err;
Specification.prototype.validateModel = function validateModel (apiDOrSO, modelIdOrRef, data, callback) {
switch (this.version) {

@@ -1298,3 +1257,3 @@ case '1.2':

if (_.isUndefined(modelIdOrPath)) {
if (_.isUndefined(modelIdOrRef)) {
throw new Error('modelId is required');

@@ -1313,4 +1272,4 @@ }

if (_.isUndefined(modelIdOrPath)) {
throw new Error('modelIdOrPath is required');
if (_.isUndefined(modelIdOrRef)) {
throw new Error('modelRef is required');
}

@@ -1321,54 +1280,100 @@

metadataEntry = getModelsMetadata(this, apiDOrSO);
modelsMetadata = metadataEntry.metadata;
if (_.isUndefined(data)) {
throw new Error('data is required');
}
// Composing a model for an invalid model hierarchy is brittle and so we will not do it
if (metadataEntry.results.errors.length > 0) {
err = new Error('The models are invalid and model composition is not possible');
err.errors = metadataEntry.results.errors;
err.warnings = metadataEntry.results.warnings;
throw err;
if (_.isUndefined(callback)) {
throw new Error('callback is required');
} else if (!_.isFunction(callback)) {
throw new TypeError('callback must be a function');
}
modelMetadata = modelsMetadata[this.version === '1.2' ?
modelIdOrPath :
refToJsonPointer(modelIdOrPath)];
this.composeModel(apiDOrSO, modelIdOrRef, function (err, result) {
if (err) {
return callback(err);
}
return _.isUndefined(modelMetadata) ? undefined : modelMetadata.composed;
validateAgainstSchema(this, result, data, callback);
}.bind(this));
};
/**
* Validates a model based on its id.
* Returns a fully resolved document or document fragment. (Does not perform validation as this is typically called
* after validation occurs.))
*
* @param {object} apiDOrSO - The Swagger Resource API Declaration (1.2) or the Swagger Object (2.0)
* @param {string} modelIdOrPath - The model id (1.2 or 2.0) or the path to the model (2.0)
* @param {object} data - The model to validate
* @param {object} document - The document to resolve or the document containing the reference to resolve
* @param {string} [ptr] - The JSON Pointer or undefined to return the whole document
* @param {resultCallback} callback - The result callback
*
* @returns undefined if validation passes or an object containing errors and/or warnings
* @returns the fully resolved document or fragment
*
* @throws Error if there are validation errors while creating
* @throws Error if there are upstream errors
*/
Specification.prototype.validateModel = function validateModel (apiDOrSO, modelIdOrPath, data) {
var modelSchema = this.composeModel(apiDOrSO, modelIdOrPath);
var result;
var validator;
Specification.prototype.resolve = function resolve (document, ptr, callback) {
var documentMetadata;
var schemaName;
var respond = function respond (document) {
if (_.isString(ptr)) {
return callback(undefined, traverse(document).get(JsonRefs.pathFromPointer(ptr)));
} else {
return callback(undefined, document);
}
};
if (_.isUndefined(modelSchema)) {
throw new Error('Unable to compose model so validation is not possible');
// Validate arguments
if (_.isUndefined(document)) {
throw new Error('document is required');
} else if (!_.isPlainObject(document)) {
throw new TypeError('document must be an object');
}
validator = createValidator(this);
result = validator.validate(modelSchema, data);
if (arguments.length === 2) {
callback = arguments[1];
ptr = undefined;
}
if (result) {
result = {
errors: validator.je(modelSchema, data, result, jjveOptions)
};
if (!_.isUndefined(ptr) && !_.isString(ptr)) {
throw new TypeError('ptr must be a JSON Pointer string');
}
if (_.isUndefined(callback)) {
throw new Error('callback is required');
} else if (!_.isFunction(callback)) {
throw new TypeError('callback must be a function');
}
documentMetadata = getDocumentCache(document);
// Swagger 1.2 is not supported due to invalid JSON References being used. Even if the JSON References were valid,
// the JSON Schema for Swagger 1.2 do not allow JavaScript objects in all places where the resoution would occur.
if (documentMetadata.swaggerVersion === '1.2') {
throw new Error('Swagger 1.2 is not supported');
}
if (!documentMetadata.resolved) {
if (documentMetadata.swaggerVersion === '1.2') {
if (_.find(['basePath', 'consumes', 'models', 'produces', 'resourcePath'], function (name) {
return !_.isUndefined(document[name]);
})) {
schemaName = 'apiDeclaration.json';
} else {
schemaName = 'resourceListing.json';
}
} else {
schemaName = 'schema.json';
}
// Ensure the document is valid first
validateAgainstSchema(this, schemaName, document, function (err, results) {
if (err) {
return callback(err);
} else if (helpers.formatResults(results)) {
return handleValidationError(results, callback);
}
return respond(documentMetadata.resolved);
});
} else {
result = undefined;
return respond(documentMetadata.resolved);
}
return result;
};

@@ -1375,0 +1380,0 @@

@@ -34,9 +34,2 @@ /*

var dateTimeRegExp = /^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$/;
var throwInvalidParameter = function throwInvalidParameter (name, message) {
var err = new Error('Parameter (' + name + ') ' + message);
err.failedValidation = true;
throw err;
};
var isValidDate = function isValidDate (date) {

@@ -104,3 +97,66 @@ var day;

var throwErrorWithCode = function throwErrorWithCode (code, msg) {
var err = new Error(msg);
err.code = code;
err.failedValidation = true;
throw err;
};
module.exports.validateAgainstSchema = function validateAgainstSchema (schemaOrName, data, validator) {
var removeParams = function (obj) {
delete obj.params;
if (obj.inner) {
_.each(obj.inner, function (nObj) {
removeParams(nObj);
});
}
};
var schema = _.isPlainObject(schemaOrName) ? _.cloneDeep(schemaOrName) : schemaOrName;
// We don't check this due to internal usage but if validator is not provided, schemaOrName must be a schema
if (_.isUndefined(validator)) {
validator = helpers.createJsonValidator([schema]);
}
var valid = validator.validate(data, schema);
if (!valid) {
try {
throwErrorWithCode('SCHEMA_VALIDATION_FAILED', 'Failed schema validation');
} catch (err) {
err.results = {
errors: _.map(validator.getLastErrors(), function (err) {
removeParams(err);
return err;
}),
warnings: []
};
throw err;
}
}
};
/**
* Validates a schema of type array is properly formed (when necessar).
*
* *param {object} schema - The schema object to validate
*
* @throws Error if the schema says it's an array but it is not formed properly
*
* @see {@link https://github.com/swagger-api/swagger-spec/issues/174}
*/
var validateArrayType = module.exports.validateArrayType = function validateArrayType (schema) {
// We have to do this manually for now
if (schema.type === 'array' && _.isUndefined(schema.items)) {
throwErrorWithCode('OBJECT_MISSING_REQUIRED_PROPERTY', 'Missing required property: items');
}
};
/**
* Validates the request's content type (when necessary).

@@ -129,5 +185,4 @@ *

/**
* Validates the request parameter's value against the allowable values (when necessary).
* Validates the value against the allowable values (when necessary).
*
* @param {string} name - The parameter name
* @param {*} val - The parameter value

@@ -138,5 +193,5 @@ * @param {string[]} allowed - The allowable values

*/
module.exports.validateEnum = function validateEnum (name, val, allowed) {
var validateEnum = module.exports.validateEnum = function validateEnum (val, allowed) {
if (!_.isUndefined(allowed) && !_.isUndefined(val) && allowed.indexOf(val) === -1) {
throwInvalidParameter(name, 'is not an allowable value (' + allowed.join(', ') + '): ' + val);
throwErrorWithCode('ENUM_MISMATCH', 'Not an allowable value (' + allowed.join(', ') + '): ' + val);
}

@@ -146,5 +201,4 @@ };

/**
* Validates the request parameter's value is less than the maximum (when necessary).
* Validates the value is less than the maximum (when necessary).
*
* @param {string} name - The parameter name
* @param {*} val - The parameter value

@@ -156,3 +210,4 @@ * @param {string} maximum - The maximum value

*/
module.exports.validateMaximum = function validateMaximum (name, val, maximum, type, exclusive) {
var validateMaximum = module.exports.validateMaximum = function validateMaximum (val, maximum, type, exclusive) {
var code = exclusive === true ? 'MAXIMUM_EXCLUSIVE' : 'MAXIMUM';
var testMax;

@@ -175,5 +230,5 @@ var testVal;

if (exclusive && testVal >= testMax) {
throwInvalidParameter(name, 'is greater than or equal to the configured maximum (' + maximum + '): ' + val);
throwErrorWithCode(code, 'Greater than or equal to the configured maximum (' + maximum + '): ' + val);
} else if (testVal > testMax) {
throwInvalidParameter(name, 'is greater than the configured maximum (' + maximum + '): ' + val);
throwErrorWithCode(code, 'Greater than the configured maximum (' + maximum + '): ' + val);
}

@@ -184,5 +239,4 @@ }

/**
* Validates the request parameter's array count is less than the maximum (when necessary).
* Validates the array count is less than the maximum (when necessary).
*
* @param {string} name - The parameter name
* @param {*[]} val - The parameter value

@@ -193,5 +247,5 @@ * @param {number} maxItems - The maximum number of items

*/
module.exports.validateMaxItems = function validateMaxItems (name, val, maxItems) {
var validateMaxItems = module.exports.validateMaxItems = function validateMaxItems (val, maxItems) {
if (!_.isUndefined(maxItems) && val.length > maxItems) {
throwInvalidParameter(name, 'contains more items than allowed: ' + maxItems);
throwErrorWithCode('ARRAY_LENGTH_LONG', 'Array is too long (' + val.length + '), maximum ' + maxItems);
}

@@ -201,5 +255,4 @@ };

/**
* Validates the request parameter's length is less than the maximum (when necessary).
* Validates the value length is less than the maximum (when necessary).
*
* @param {string} name - The parameter name
* @param {*[]} val - The parameter value

@@ -210,5 +263,5 @@ * @param {number} maxLength - The maximum length

*/
module.exports.validateMaxLength = function validateMaxLength (name, val, maxLength) {
var validateMaxLength = module.exports.validateMaxLength = function validateMaxLength (val, maxLength) {
if (!_.isUndefined(maxLength) && val.length > maxLength) {
throwInvalidParameter(name, 'is longer than allowed: ' + maxLength);
throwErrorWithCode('MAX_LENGTH', 'String is too long (' + val.length + ' chars), maximum ' + maxLength);
}

@@ -218,5 +271,21 @@ };

/**
* Validates the request parameter's array count is greater than the minimum (when necessary).
* Validates the value's property count is greater than the maximum (when necessary).
*
* @param {string} name - The parameter name
* @param {*[]} val - The parameter value
* @param {number} minProperties - The maximum number of properties
*
* @throws Error if the value's property count is less than the maximum
*/
var validateMaxProperties = module.exports.validateMaxProperties = function validateMaxLength (val, maxProperties) {
var propCount = _.isPlainObject(val) ? Object.keys(val).length : 0;
if (!_.isUndefined(maxProperties) && propCount > maxProperties) {
throwErrorWithCode('MAX_PROPERTIES',
'Number of properties is too many (' + propCount + ' properties), maximum ' + maxProperties);
}
};
/**
* Validates the value array count is greater than the minimum (when necessary).
*
* @param {*} val - The parameter value

@@ -228,3 +297,4 @@ * @param {string} minimum - The minimum value

*/
module.exports.validateMinimum = function validateMinimum (name, val, minimum, type, exclusive) {
var validateMinimum = module.exports.validateMinimum = function validateMinimum (val, minimum, type, exclusive) {
var code = exclusive === true ? 'MINIMUM_EXCLUSIVE' : 'MINIMUM';
var testMin;

@@ -247,5 +317,5 @@ var testVal;

if (exclusive && testVal <= testMin) {
throwInvalidParameter(name, 'is less than or equal to the configured minimum (' + minimum + '): ' + val);
throwErrorWithCode(code, 'Less than or equal to the configured minimum (' + minimum + '): ' + val);
} else if (testVal < testMin) {
throwInvalidParameter(name, 'is less than the configured minimum (' + minimum + '): ' + val);
throwErrorWithCode(code, 'Less than the configured minimum (' + minimum + '): ' + val);
}

@@ -256,5 +326,4 @@ }

/**
* Validates the request parameter's value contains fewer items than allowed (when necessary).
* Validates the value value contains fewer items than allowed (when necessary).
*
* @param {string} name - The parameter name
* @param {*[]} val - The parameter value

@@ -265,5 +334,5 @@ * @param {number} minItems - The minimum number of items

*/
module.exports.validateMinItems = function validateMinItems (name, val, minItems) {
var validateMinItems = module.exports.validateMinItems = function validateMinItems (val, minItems) {
if (!_.isUndefined(minItems) && val.length < minItems) {
throwInvalidParameter(name, 'contains fewer items than allowed: ' + minItems);
throwErrorWithCode('ARRAY_LENGTH_SHORT', 'Array is too short (' + val.length + '), minimum ' + minItems);
}

@@ -273,5 +342,4 @@ };

/**
* Validates the request parameter's length is greater than the minimum (when necessary).
* Validates the value length is less than the minimum (when necessary).
*
* @param {string} name - The parameter name
* @param {*[]} val - The parameter value

@@ -282,5 +350,5 @@ * @param {number} minLength - The minimum length

*/
module.exports.validateMinLength = function validateMinLength (name, val, minLength) {
var validateMinLength = module.exports.validateMinLength = function validateMinLength (val, minLength) {
if (!_.isUndefined(minLength) && val.length < minLength) {
throwInvalidParameter(name, 'is shorter than allowed: ' + minLength);
throwErrorWithCode('MIN_LENGTH', 'String is too short (' + val.length + ' chars), minimum ' + minLength);
}

@@ -290,34 +358,29 @@ };

/**
* Validtes the request parameter against its model schema.
* Validates the value's property count is less than or equal to the minimum (when necessary).
*
* @param {string} name - The parameter name
* @param {object} val - The parameter value
* @param {string} version - The Swagger version
* @param {object} apiDOrSO - The Swagger API Declaration (1.2) or Swagger Object (2.0)
* @param {string} modelIdOrPath - The model id or path
* @param {*[]} val - The parameter value
* @param {number} minProperties - The minimum number of properties
*
* @throws Error if the value is not a valid model
* @throws Error if the value's property count is less than the minimum
*/
module.exports.validateModel = function validateModel (name, val, version, apiDOrSO, modelIdOrPath) {
var spec = helpers.getSpec(version);
var validate = function validate (data) {
var result = spec.validateModel(apiDOrSO, modelIdOrPath, data);
var validateMinProperties = module.exports.validateMinProperties = function validateMinLength (val, minProperties) {
var propCount = _.isPlainObject(val) ? Object.keys(val).length : 0;
if (!_.isUndefined(result)) {
try {
throwInvalidParameter(name, 'is not a valid ' + modelIdOrPath + ' model');
} catch (err) {
err.errors = result.errors;
if (!_.isUndefined(minProperties) && propCount < minProperties) {
throwErrorWithCode('MIN_PROPERTIES',
'Number of properties is too few (' + propCount + ' properties), minimum ' + minProperties);
}
};
throw err;
}
}
};
if (_.isArray(val)) {
_.each(val, function (item) {
validate(item);
});
} else {
validate(val);
/**
* Validates the value is a multiple of the provided number (when necessary).
*
* @param {*[]} val - The parameter value
* @param {number} multipleOf - The number that should divide evenly into the value
*
* @throws Error if the value contains fewer items than allowable
*/
var validateMultipleOf = module.exports.validateMultipleOf = function validateMultipleOf (val, multipleOf) {
if (!_.isUndefined(multipleOf) && val % multipleOf !== 0) {
throwErrorWithCode('MULTIPLE_OF', 'Not a multiple of ' + multipleOf);
}

@@ -327,3 +390,3 @@ };

/**
* Validates the request parameter's matches a pattern (when necessary).
* Validates the value matches a pattern (when necessary).
*

@@ -336,5 +399,5 @@ * @param {string} name - The parameter name

*/
module.exports.validatePattern = function validatePattern (name, val, pattern) {
var validatePattern = module.exports.validatePattern = function validatePattern (val, pattern) {
if (!_.isUndefined(pattern) && _.isNull(val.match(new RegExp(pattern)))) {
throwInvalidParameter(name, 'does not match required pattern: ' + pattern);
throwErrorWithCode('PATTERN', 'Does not match required pattern: ' + pattern);
}

@@ -344,5 +407,4 @@ };

/**
* Validates the request parameter's requiredness (when necessary).
* Validates the value requiredness (when necessary).
*
* @param {string} name - The parameter name
* @param {*} val - The parameter value

@@ -353,5 +415,5 @@ * @param {boolean} required - Whether or not the parameter is required

*/
module.exports.validateRequiredness = function validateRequiredness (name, val, required) {
module.exports.validateRequiredness = function validateRequiredness (val, required) {
if (!_.isUndefined(required) && required === true && _.isUndefined(val)) {
throwInvalidParameter(name, 'is required');
throwErrorWithCode('REQUIRED', 'Is required');
}

@@ -361,5 +423,4 @@ };

/**
* Validates the request parameter's type and format (when necessary).
* Validates the value type and format (when necessary).
*
* @param {string} name - The parameter name
* @param {*} val - The parameter value

@@ -372,48 +433,49 @@ * @param {string} type - The parameter type

*/
module.exports.validateTypeAndFormat = function validateTypeAndFormat (name, val, type, format, skipError) {
var result = true;
var validateTypeAndFormat = module.exports.validateTypeAndFormat =
function validateTypeAndFormat (val, type, format, skipError) {
var result = true;
if (_.isArray(val)) {
_.each(val, function (aVal, index) {
if (!validateTypeAndFormat(name, aVal, type, format, true)) {
throwInvalidParameter(name, 'at index ' + index + ' is not a valid ' + type + ': ' + aVal);
}
});
} else {
switch (type) {
case 'boolean':
result = _.isBoolean(val) || ['false', 'true'].indexOf(val) !== -1;
break;
case 'integer':
result = !_.isNaN(parseInt(val, 10));
break;
case 'number':
result = !_.isNaN(parseFloat(val));
break;
case 'string':
if (!_.isUndefined(format)) {
switch (format) {
case 'date':
result = isValidDate(val);
break;
case 'date-time':
result = isValidDateTime(val);
break;
if (_.isArray(val)) {
_.each(val, function (aVal, index) {
if (!validateTypeAndFormat(aVal, type, format, true)) {
throwErrorWithCode('INVALID_TYPE', 'Value at index ' + index + ' is not a valid ' + type + ': ' + aVal);
}
});
} else {
switch (type) {
case 'boolean':
result = _.isBoolean(val) || ['false', 'true'].indexOf(val) !== -1;
break;
case 'integer':
result = !_.isNaN(parseInt(val, 10));
break;
case 'number':
result = !_.isNaN(parseFloat(val));
break;
case 'string':
if (!_.isUndefined(format)) {
switch (format) {
case 'date':
result = isValidDate(val);
break;
case 'date-time':
result = isValidDateTime(val);
break;
}
}
break;
}
break;
}
}
if (skipError) {
return result;
} else if (!result) {
throwInvalidParameter(name, 'is not a valid ' + (_.isUndefined(format) ? '' : format + ' ') + type + ': ' + val);
}
};
if (skipError) {
return result;
} else if (!result) {
throwErrorWithCode('INVALID_TYPE',
'Not a valid ' + (_.isUndefined(format) ? '' : format + ' ') + type + ': ' + val);
}
};
/**
* Validates the request parameter's values are unique (when necessary).
* Validates the value values are unique (when necessary).
*
* @param {string} name - The parameter name
* @param {string[]} val - The parameter value

@@ -424,6 +486,106 @@ * @param {boolean} isUnique - Whether or not the parameter values are unique

*/
module.exports.validateUniqueItems = function validateUniqueItems (name, val, isUnique) {
var validateUniqueItems = module.exports.validateUniqueItems = function validateUniqueItems (val, isUnique) {
if (!_.isUndefined(isUnique) && _.uniq(val).length !== val.length) {
throwInvalidParameter(name, 'does not allow duplicate values: ' + val.join(', '));
throwErrorWithCode('ARRAY_UNIQUE', 'Does not allow duplicate values: ' + val.join(', '));
}
};
/**
* Validates the value against the schema.
*
* @param {string} swaggerVersion - The Swagger version
* @param {object} schema - The schema to use to validate things
* @param {string[]} path - The path to the schema
* @param {*} [val] - The value to validate or undefined to use the default value provided by the schema
*
* @throws Error if any validation failes
*/
module.exports.validateSchemaConstraints = function validateSchemaConstraints (swaggerVersion, schema, path, val) {
var resolveSchema = function resolveSchema (schema) {
var resolved = schema;
if (resolved.schema) {
path = path.concat(['schema']);
resolved = resolveSchema(resolved.schema);
}
return resolved;
};
// Resolve the actual schema object
schema = resolveSchema(schema);
try {
// Always perform this check even if there is no value
if (schema.type === 'array') {
validateArrayType(schema);
}
// Default to default value if necessary
if (_.isUndefined(val)) {
val = swaggerVersion === '1.2' ? schema.defaultValue : schema.default;
path = path.concat([swaggerVersion === '1.2' ? 'defaultValue' : 'default']);
}
// If there is no explicit default value, return as all validations will fail
if (_.isUndefined(val)) {
return;
}
if (schema.type === 'array') {
if (!_.isUndefined(schema.items)) {
validateTypeAndFormat(val, schema.type === 'array' ? schema.items.type : schema.type,
schema.type === 'array' && schema.items.format ?
schema.items.format :
schema.format);
} else {
validateTypeAndFormat(val, schema.type, schema.format);
}
} else {
validateTypeAndFormat(val, schema.type, schema.format);
}
// Validate enum
validateEnum(val, schema.enum);
// Validate maximum
validateMaximum(val, schema.maximum, schema.type, schema.exclusiveMaximum);
// Validate maxItems (Swagger 2.0+)
validateMaxItems(val, schema.maxItems);
// Validate maxLength (Swagger 2.0+)
validateMaxLength(val, schema.maxLength);
// Validate maxProperties (Swagger 2.0+)
validateMaxProperties(val, schema.maxProperties);
// Validate minimum
validateMinimum(val, schema.minimum, schema.type, schema.exclusiveMinimum);
// Validate minItems
validateMinItems(val, schema.minItems);
// Validate minLength (Swagger 2.0+)
validateMinLength(val, schema.minLength);
// Validate minProperties (Swagger 2.0+)
validateMinProperties(val, schema.minProperties);
// Validate multipleOf (Swagger 2.0+)
validateMultipleOf(val, schema.multipleOf);
// Validate pattern (Swagger 2.0+)
validatePattern(val, schema.pattern);
// Validate uniqueItems
validateUniqueItems(val, schema.uniqueItems);
} catch (err) {
err.path = path;
throw err;
}
};

@@ -29,3 +29,2 @@ /*

var helpers = require('../helpers');
var expressStylePath = helpers.expressStylePath;
var parseurl = require('parseurl');

@@ -68,31 +67,37 @@ var pathToRegexp = require('path-to-regexp');

var apis = {};
var apiCache = {};
// Gather the apis, their path regex patterns and the corresponding operations
_.each(resources, function (resource, index) {
_.each(resource.apis, function (api) {
_.each(resources, function (resource, resourceIndex) {
_.each(resource.apis, function (api, apiIndex) {
var expressPath = helpers.expressStylePath(resource.basePath, api.path);
var keys = [];
var re = pathToRegexp(expressStylePath(resource.basePath, api.path), keys);
var reStr = re.toString();
var re = pathToRegexp(expressPath, keys);
var cacheKey = re.toString();
if (Object.keys(apis).indexOf(reStr) !== -1) {
throw new Error('Duplicate API path/pattern: ' + api.path);
// This is an absolute path, use it as the cache key
if (expressPath.indexOf('{') === -1) {
cacheKey = expressPath;
}
apis[reStr] = {
// For absolute paths, store it instead of its regex
apiCache[cacheKey] = {
api: api,
apiDeclaration: resource,
apiIndex: apiIndex,
keys: keys,
params: {},
re: re,
resourceIndex: index,
operations: {}
operations: {},
resourceIndex: resourceIndex,
resourceListing: resourceList
};
_.each(api.operations, function (operation) {
_.each(api.operations, function (operation, operationIndex) {
var method = operation.method;
if (!_.isUndefined(apis[reStr][method])) {
throw new Error('Duplicate API operation (' + api.path + ') method: ' + method);
}
apis[reStr].operations[method] = operation;
apiCache[cacheKey].operations[method] = {
operation: operation,
operationPath: ['apis', apiIndex.toString(), 'operations', operationIndex.toString()]
};
});

@@ -104,78 +109,45 @@ });

var path = parseurl(req).pathname;
var apiMetadata;
var match;
var api = _.find(apis, function (api) {
match = api.re.exec(path);
return _.isArray(match);
});
var metadata = {
api: api ? api.api : undefined,
apiDeclaration: api ? resources[api.resourceIndex] : undefined,
authorizations: resourceList.authorizations || {},
models: api ? resources[api.resourceIndex].models || {} : {},
operation: api ? api.operations[req.method] : undefined,
params: {},
resourceListing: resourceList
};
var metadata;
// Attach Swagger metadata to the request
if (!_.isUndefined(api)) {
req.swagger = metadata;
}
try {
apiMetadata = apiCache[path] || _.find(apiCache, function (metadata) {
match = metadata.re.exec(path);
return _.isArray(match);
});
// Collect the parameter values
if (!_.isUndefined(metadata.operation)) {
try {
_.each(metadata.operation.parameters, function (param) {
var val;
if (apiMetadata) {
metadata = {
api: apiMetadata.api,
apiDeclaration: apiMetadata.apiDeclaration,
apiIndex: apiMetadata.apiIndex,
params: {},
resourceIndex: apiMetadata.resourceIndex,
resourceListing: apiMetadata.resourceListing
};
// Get the value to validate based on the operation parameter type
switch (param.paramType) {
case 'body':
case 'form':
if (!req.body) {
throw new Error('Server configuration error: req.body is not defined but is required');
}
if (_.isPlainObject(apiMetadata.operations[req.method])) {
metadata.operation = apiMetadata.operations[req.method].operation;
metadata.operationPath = apiMetadata.operations[req.method].operationPath;
metadata.authorizations = metadata.operation.authorizations || apiMetadata.apiDeclaration.authorizations;
}
if (helpers.isModelParameter('1.2', param)) {
val = req.body;
} else {
val = req.body[param.name];
}
req.swagger = metadata;
}
break;
case 'header':
val = req.headers[param.name];
// Collect the parameter values
if (metadata && metadata.operation) {
_.each(metadata.operation.parameters, function (parameter, index) {
var val = helpers.getParameterValue('1.2', parameter, apiMetadata.keys, match, req);
break;
case 'path':
_.each(api.keys, function (key, index) {
if (key.name === param.name) {
val = match[index + 1];
}
});
break;
case 'query':
if (!req.query) {
throw new Error('Server configuration error: req.query is not defined but is required');
}
val = req.query[param.name];
break;
}
// Use the default value when necessary
if (_.isUndefined(val) && !_.isUndefined(param.defaultValue)) {
val = param.defaultValue;
}
metadata.params[param.name] = {
schema: param,
metadata.params[parameter.name] = {
path: metadata.operationPath.concat(['parameters', index.toString()]),
schema: parameter,
value: val
};
});
} catch (err) {
return next(err);
}
} catch (err) {
return next(err);
}

@@ -182,0 +154,0 @@

@@ -29,7 +29,2 @@ /*

var helpers = require('../helpers');
var createStubHandler = helpers.createStubHandler;
var getHandlerName = helpers.getHandlerName;
var handlerCacheFromDir = helpers.handlerCacheFromDir;
var send405 = helpers.send405;
var specVer = '1.2';

@@ -79,3 +74,3 @@ var defaultOptions = {

// Create the handler cache from the modules in the controllers directory
handlerCache = handlerCacheFromDir(options.controllers);
handlerCache = helpers.handlerCacheFromDir(options.controllers);
}

@@ -93,9 +88,9 @@

if (_.isUndefined(operation)) {
return send405(specVer, req, res, next);
return helpers.send405('1.2', req, res, next);
} else {
handlerName = getHandlerName(specVer, req);
handlerName = helpers.getHandlerName('1.2', req);
handler = handlerCache[handlerName];
if (_.isUndefined(handler) && options.useStubs === true) {
handler = handlerCache[handlerName] = createStubHandler(req, res, specVer);
handler = handlerCache[handlerName] = helpers.createStubHandler('1.2', req, res, next, handlerName);
}

@@ -102,0 +97,0 @@

@@ -53,3 +53,2 @@ /*

var apiDocsPaths = [];
var rlApiPaths = [];
var staticMiddleware = serveStatic(path.join(__dirname, '..', 'swagger-ui'), staticOptions);

@@ -86,11 +85,2 @@ var apiDocsHandler = function apiDocsHandler (res, path) {

// Create the apiPaths list
_.each(resourceList.apis, function (api) {
if (rlApiPaths.indexOf(api.path) > -1) {
throw new Error('API path declared multiple times: ' + api.path);
}
rlApiPaths.push(api.path);
});
// Add the Resource Listing to the response cache

@@ -101,6 +91,2 @@ apiDocsCache[options.apiDocs] = JSON.stringify(resourceList, null, 2);

_.each(resources, function (resource, resourcePath) {
if (rlApiPaths.indexOf(resourcePath) === -1) {
throw new Error('resource path is not defined in the resource listing: ' + resourcePath);
}
// Respond with pretty JSON (Configurable?)

@@ -107,0 +93,0 @@ apiDocsCache[options.apiDocs + resourcePath] = JSON.stringify(resource, null, 2);

@@ -28,5 +28,6 @@ /*

var _ = require('lodash');
var async = require('async');
var helpers = require('../helpers');
var isModelParameter = helpers.isModelParameter;
var send400 = helpers.send400;
var spec = require('../../lib/helpers').getSpec('1.2');
var validators = require('../../lib/validators');

@@ -47,2 +48,6 @@

if (!_.isUndefined(operation)) {
var paramIndex = 0;
var paramName; // Here since we use it in the catch block
var paramPath; // Here since we use it in the catch block
// Validate the request

@@ -53,48 +58,71 @@ try {

_.each(operation.parameters || [], function (param) {
var paramName = param.name;
var val = req.swagger.params[paramName].value;
async.map(operation.parameters, function (parameter, oCallback) {
var isModel = helpers.isModelParameter('1.2', parameter);
var val;
paramName = parameter.name;
paramPath = req.swagger.operationPath.concat(['params', paramIndex.toString()]);
val = req.swagger.params[paramName].value;
// Validate requiredness
validators.validateRequiredness(paramName, val, param.required);
validators.validateRequiredness(val, parameter.required);
// Quick return if the value is not present
if (_.isUndefined(val)) {
return;
return oCallback();
}
if (isModelParameter('1.2', param)) {
// Validate the model
validators.validateModel(paramName, val, '1.2', req.swagger.apiDeclaration,
param.type === 'array' && !_.isUndefined(param.items.$ref) ?
param.items.$ref :
param.type);
} else {
// Validate the value type/format
validators.validateTypeAndFormat(paramName, val,
param.type === 'array' ? param.items.type : param.type,
param.type === 'array' && param.items.format ?
param.items.format :
param.format);
validators.validateSchemaConstraints('1.2', parameter, paramPath, val);
// Validate enum
validators.validateEnum(paramName, val, param.enum);
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');
// Validate maximum
validators.validateMaximum(paramName, val, param.maximum, param.type);
err.code = 'SCHEMA_VALIDATION_FAILED';
err.errors = results.errors;
err.failedValidation = true;
// Validate minimum
validators.validateMinimum(paramName, val, param.minimum, param.type);
return false;
}
});
}
// Validate uniqueItems
validators.validateUniqueItems(paramName, val, param.uniqueItems);
oCallback(err);
});
} else {
oCallback();
}
paramIndex++;
}, function (err) {
if (err) {
throw err;
} else {
return next();
}
});
} catch (err) {
if (err.failedValidation === true) {
if (!err.path) {
err.path = paramPath;
}
err.paramName = paramName;
}
return send400(req, res, next, err);
}
} else {
return next();
}
return next();
};
};

@@ -32,3 +32,29 @@ /*

var pathToRegexp = require('path-to-regexp');
var spec = require('../../lib/helpers').getSpec('2.0');
var composeParameters = function composeParameters (apiPath, method, path, operation) {
var cParams = [];
var seenParams = [];
_.each(operation.parameters, function (parameter, index) {
cParams.push({
path: apiPath.concat([method, 'parameters', index.toString()]),
schema: parameter
});
seenParams.push(parameter.name + ':' + parameter.in);
});
_.each(path.parameters, function (parameter, index) {
if (seenParams.indexOf(parameter.name + ':' + parameter.in) === -1) {
cParams.push({
path: apiPath.concat(['parameters', index.toString()]),
schema: parameter
});
}
});
return cParams;
};
/**

@@ -60,24 +86,42 @@ * Middleware for providing Swagger information to downstream middleware and request handlers. 'req.swagger' will be

var paths = {};
var apiCache = {};
// Gather the paths, their path regex patterns and the corresponding operations
_.each(swaggerObject.paths, function (path, pathName) {
var keys = [];
var re = pathToRegexp(expressStylePath(swaggerObject.basePath, pathName), keys);
var reStr = re.toString();
// To avoid running into issues with references throughout the Swagger object we will use the resolved version.
// Getting the resolved version is an asynchronous process but since initializeMiddleware caches the resolved document
// this is a synchronous action at this point.
spec.resolve(swaggerObject, function (err, resolved) {
// Gather the paths, their path regex patterns and the corresponding operations
_.each(resolved.paths, function (path, pathName) {
var expressPath = expressStylePath(resolved.basePath, pathName);
var keys = [];
var re = pathToRegexp(expressPath, keys);
var cacheKey = re.toString();
paths[reStr] = {
apiPath: pathName,
path: path,
keys: keys,
re: re,
operations: {}
};
// This is an absolute path, use it as the cache key
if (expressPath.indexOf('{') === -1) {
cacheKey = expressPath;
}
_.each(['get', 'put', 'post', 'delete', 'options', 'head', 'patch'], function (method) {
var operation = path[method];
apiCache[cacheKey] = {
apiPath: pathName,
path: path,
keys: keys,
re: re,
operations: {},
swaggerObject: {
original: swaggerObject,
resolved: resolved
}
};
if (!_.isUndefined(operation)) {
paths[reStr].operations[method] = operation;
}
_.each(['get', 'put', 'post', 'delete', 'options', 'head', 'patch'], function (method) {
var operation = path[method];
if (!_.isUndefined(operation)) {
apiCache[cacheKey].operations[method] = {
operation: operation,
parameters: composeParameters(['paths', pathName], method, path, operation)
};
}
});
});

@@ -87,105 +131,45 @@ });

return function swaggerMetadata (req, res, next) {
var rPath = parseurl(req).pathname;
var path = parseurl(req).pathname;
var match;
var path = _.find(paths, function (path) {
match = path.re.exec(rPath);
return _.isArray(match);
});
var metadata = {
apiPath : path ? path.apiPath : undefined,
path: path ? path.path : undefined,
operation: path ? path.operations[req.method.toLowerCase()] : undefined,
params: {},
swaggerObject: swaggerObject
};
var metadata;
var pathMetadata;
// Attach Swagger metadata to the request
if (!_.isUndefined(path)) {
req.swagger = metadata;
}
try {
pathMetadata = apiCache[path] || _.find(apiCache, function (metadata) {
match = metadata.re.exec(path);
return _.isArray(match);
});
// Collect the parameter values
if (!_.isUndefined(metadata.operation)) {
try {
// Until Swagger 2.0 documentation comes out, I'm going to assume that you cannot override "path" parameters
// with operation parameters. That's why we start with the path parameters first and then the operation
// parameters. (Note: "path" in this context is a path entry at #/paths in the Swagger Object)
_.each(_.union(metadata.path.parameters, metadata.operation.parameters), function (param) {
var paramPath = ['paths', path.apiPath];
var paramType = param.in;
var findIndex = function (params, name) {
var foundIndex;
if (pathMetadata) {
metadata = {
apiPath : pathMetadata.apiPath,
path: pathMetadata.path,
params: {},
swaggerObject: pathMetadata.swaggerObject.resolved
};
_.each(params, function (param, index) {
if (param.in === paramType && param.name === name) {
foundIndex = index;
return false;
}
});
if (_.isPlainObject(pathMetadata.operations[req.method.toLowerCase()])) {
metadata.operation = pathMetadata.operations[req.method.toLowerCase()].operation;
metadata.operationParameters = pathMetadata.operations[req.method.toLowerCase()].parameters || [];
metadata.security = metadata.operation.security || metadata.swaggerObject.security || [];
}
return foundIndex;
};
var paramIndex = findIndex(metadata.path.parameters, param.name);
var val;
req.swagger = metadata;
}
// Get the value to validate based on the operation parameter type
switch (paramType) {
case 'body':
case 'formData':
if (!req.body) {
throw new Error('Server configuration error: req.body is not defined but is required');
}
// Collect the parameter values
if (metadata && metadata.operation) {
_.each(metadata.operationParameters, function (paramMetadata) {
var parameter = paramMetadata.schema;
var val = helpers.getParameterValue('2.0', parameter, pathMetadata.keys, match, req);
if (helpers.isModelParameter('2.0', param)) {
val = req.body;
} else {
val = req.body[param.name];
}
break;
case 'header':
val = req.headers[param.name];
break;
case 'path':
_.each(path.keys, function (key, index) {
if (key.name === param.name) {
val = match[index + 1];
}
});
break;
case 'query':
if (!req.query) {
throw new Error('Server configuration error: req.query is not defined but is required');
}
val = req.query[param.name];
break;
}
// Use the default value when necessary
if (_.isUndefined(val) && !_.isUndefined(param.schema) && !_.isUndefined(param.schema.default)) {
val = param.schema.default;
}
// Figure out the parameter path
if (_.isUndefined(paramIndex)) {
paramPath.push(req.method.toLowerCase());
paramIndex = findIndex(metadata.operation.parameters, param.name);
}
paramPath.push('parameters', paramIndex);
metadata.params[param.name] = {
path: paramPath,
schema: param,
metadata.params[parameter.name] = {
path: paramMetadata.path,
schema: parameter,
value: val
};
});
} catch (err) {
return next(err);
}
} catch (err) {
return next(err);
}

@@ -192,0 +176,0 @@

@@ -29,7 +29,2 @@ /*

var helpers = require('../helpers');
var createStubHandler = helpers.createStubHandler;
var getHandlerName = helpers.getHandlerName;
var handlerCacheFromDir = helpers.handlerCacheFromDir;
var send405 = helpers.send405;
var specVer = '2.0';

@@ -83,3 +78,3 @@ var defaultOptions = {

// Create the handler cache from the modules in the controllers directory
handlerCache = handlerCacheFromDir(options.controllers);
handlerCache = helpers.handlerCacheFromDir(options.controllers);
}

@@ -90,3 +85,2 @@

var handlerName;
var responseModel;
var operation;

@@ -99,19 +93,9 @@

if (_.isUndefined(operation)) {
return send405(specVer, req, res, next);
return helpers.send405('2.0', req, res, next);
} else {
handlerName = getHandlerName(specVer, req);
handlerName = helpers.getHandlerName('2.0', req);
handler = handlerCache[handlerName];
if (_.isUndefined(handler) && options.useStubs === true) {
responseModel = _.find(operation.responses, function (responseModel, responseCode) {
if (responseCode === '200') {
return responseModel.responseModel;
}
});
if (_.isUndefined(responseModel)) {
responseModel = operation.responses.default;
}
handler = handlerCache[handlerName] = createStubHandler(req, res, specVer, handlerName, responseModel);
handler = handlerCache[handlerName] = helpers.createStubHandler('2.0', req, res, next, handlerName);
}

@@ -118,0 +102,0 @@

@@ -29,3 +29,3 @@ /*

function handleSecurityError(err, res) {
function handleSecurityError (err, res) {
var body = {

@@ -36,2 +36,3 @@ 'error_description': err.message,

};
if (err.headers) {

@@ -42,2 +43,3 @@ _.each(_.keys(err.headers), function(name) {

}
res.statusCode = err.statusCode || 403;

@@ -72,38 +74,33 @@ res.end(JSON.stringify(body));

*/
exports = module.exports = function swaggerSecurityMiddleware(options) {
exports = module.exports = function swaggerSecurityMiddleware (options) {
var handlers = options || {};
return function swaggerSecurity(req, res, next) {
return function swaggerSecurity (req, res, next) {
if (!req.swagger || !req.swagger.operation) { return next(); }
if (!req.swagger) { return next(); }
var securityReqs = req.swagger.operation.security || req.swagger.swaggerObject.security;
var securityReqs = req.swagger.operation.security || req.swagger.swaggerObject.security;
if (!securityReqs) { return next(); }
async.map(securityReqs, function(secReq, cb) { // logical OR - any one can allow
async.map(Object.keys(secReq), function(name, cb) { // logical AND - all must allow
var secDef = req.swagger.swaggerObject.securityDefinitions[name];
if (!secDef) { return cb(new Error('unknown security definition: ' + name)); }
var handler = handlers[name];
var handler = handlers[name];
if (!handler) { return cb(new Error('unknown security handler: ' + name)); }
handler(req, secDef, secReq[name], cb);
},
function(err) {
// swap normal err and result to short-circuit the logical OR
if (err) { return cb(undefined, err); }
cb(new Error('OK'));
}
);
},
function(ok, errors) { // note swapped results
if (ok && ok.message === 'OK') { return next(); }
handleSecurityError(errors[0], res);
}
);
}, function (err) {
// swap normal err and result to short-circuit the logical OR
if (err) { return cb(undefined, err); }
cb(new Error('OK'));
});
}, function (ok, errors) { // note swapped results
if (ok && ok.message === 'OK') { return next(); }
handleSecurityError(errors[0], res);
});
};
};

@@ -28,5 +28,4 @@ /*

var _ = require('lodash');
var async = require('async');
var helpers = require('../helpers');
var isModelParameter = helpers.isModelParameter;
var toJsonPointer = require('../../lib/helpers').toJsonPointer;
var send400 = helpers.send400;

@@ -48,2 +47,5 @@ var validators = require('../../lib/validators');

if (!_.isUndefined(operation)) {
var paramName; // Here since we use it in the catch block
var paramPath; // Here since we use it in the catch block
// Validate the request

@@ -54,73 +56,58 @@ try {

_.each(_.union(req.swagger.path.parameters, operation.parameters), function (param) {
var paramName = param.name;
var paramPath = req.swagger.params[paramName].path;
var val = req.swagger.params[paramName].value;
async.map(req.swagger.operationParameters, function (paramMetadata, oCallback) {
var parameter = paramMetadata.schema;
var isModel = helpers.isModelParameter('2.0', parameter);
var val;
paramName = parameter.name;
paramPath = paramMetadata.path;
val = req.swagger.params[paramName].value;
// Validate requiredness
validators.validateRequiredness(paramName, val, param.required);
validators.validateRequiredness(val, parameter.required);
// Quick return if the value is not present
if (_.isUndefined(val)) {
return;
return oCallback();
}
if (isModelParameter('2.0', param)) {
if (param.schema) {
paramPath.push('schema');
}
validators.validateSchemaConstraints('2.0', parameter, paramPath, val);
// Validate the model
validators.validateModel(paramName, val, '2.0', req.swagger.swaggerObject,
_.isUndefined(param.schema.$ref) ?
toJsonPointer(paramPath) :
param.schema.$ref);
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 {
// Constraints can appear in the parameter itself (type/format) and in the parameter's schema (if available)
if (param.schema) {
param = param.schema;
}
// Validate the value type/format
validators.validateTypeAndFormat(paramName, val,
param.type === 'array' ? param.items.type : param.type,
param.type === 'array' && param.items.format ?
param.items.format :
param.format);
// Validate enum
validators.validateEnum(paramName, val, param.enum);
// Validate maximum
validators.validateMaximum(paramName, val, param.maximum, param.type, param.exclusiveMaximum);
// Validate maximum items
validators.validateMaxItems(paramName, val, param.maxItems);
// Validate maximum length
validators.validateMaxLength(paramName, val, param.maxLength);
// Validate minimum
validators.validateMinimum(paramName, val, param.minimum, param.type, param.exclusiveMinimum);
// Validate minimum items
validators.validateMinItems(paramName, val, param.minItems);
// Validate minimum length
validators.validateMinLength(paramName, val, param.minLength);
// Validate pattern
validators.validatePattern(paramName, val, param.pattern);
// Validate uniqueItems
validators.validateUniqueItems(paramName, val, param.uniqueItems);
oCallback();
}
}, function (err) {
if (err) {
throw err;
} else {
return next();
}
});
} catch (err) {
if (err.failedValidation === true) {
if (!err.path) {
err.path = paramPath;
}
err.paramName = paramName;
}
return send400(req, res, next, err);
}
} else {
return next();
}
return next();
};
};

@@ -43,2 +43,6 @@ /*

var isModelType = function isModelType (spec, type) {
return spec.primitives.indexOf(type) === -1;
};
/**

@@ -74,3 +78,3 @@ * Returns an Express style path for the Swagger path.

var getHandlerName = module.exports.getHandlerName = function getHandlerName (version, req) {
module.exports.getHandlerName = function getHandlerName (version, req) {
var handlerName;

@@ -98,2 +102,6 @@

if (!schema.type) {
schema.type = 'object';
}
switch (schema.type) {

@@ -150,2 +158,8 @@ case 'array':

_.each(schema.allOf, function (parentSchema) {
_.each(parentSchema.properties, function (property, propName) {
value[propName] = getMockValue(version, property);
});
});
_.each(schema.properties, function (property, propName) {

@@ -196,12 +210,16 @@ value[propName] = getMockValue(version, property);

var mockResponse = function mockResponse (version, req) {
var mockResponse = function mockResponse (version, req, res, next, handlerName) {
var method = req.method.toLowerCase();
var operation = req.swagger.operation;
var stubResponse = 'Stubbed response for ' + getHandlerName(version, req);
var sendResponse = function sendResponse (err, response) {
if (err) {
return next(err);
} else {
return res.end(response);
}
};
var spec = helpers.getSpec(version);
var stubResponse = 'Stubbed response for ' + handlerName;
var apiDOrSO;
var composedModel;
var response;
var responseCode; // (2.0)
var responseType;
var spec = helpers.getSpec(version);

@@ -213,6 +231,2 @@ switch (version) {

if (spec.primitives.indexOf(operation.type) === -1) {
responseType = operation.type;
}
break;

@@ -223,51 +237,35 @@

if (method === 'post' && _.isPlainObject(operation.responses['201'])) {
responseCode = '201';
} else if (_.isPlainObject(operation.responses['200'])) {
responseCode = '200';
} else if (_.isPlainObject(operation.responses.default)) {
responseCode = 'default';
if (method === 'post' && operation.responses['201']) {
responseType = operation.responses['201'].schema;
} else if (operation.responses['200']) {
responseType = operation.responses['200'];
} else if (operation.responses['default']) {
responseType = operation.responses['default'];
} else if (operation.schema) {
responseType = operation.schema.type || 'object';
} else {
responseType = operation.type;
}
if (!_.isUndefined(responseCode)) {
responseType = operation.responses[responseCode];
}
if (_.isPlainObject(responseType)) {
if (_.isUndefined(responseType.schema.$ref)) {
responseType = helpers.toJsonPointer(['paths', req.swagger.apiPath, method, 'responses', responseCode,
'schema']);
} else {
responseType = helpers.refToJsonPointer(responseType.schema.$ref);
}
}
break;
}
if (_.isUndefined(responseType)) {
// Should never happen but handle it safely
response = stubResponse;
} else if (spec.primitives.indexOf(responseType) === -1) {
// This is a model
try {
composedModel = spec.composeModel(apiDOrSO, responseType);
} catch (err) {
response = JSON.stringify({
message: err.message,
stack: err.stack
if (_.isPlainObject(responseType) || isModelType(spec, responseType)) {
if (version === '1.2') {
spec.composeModel(apiDOrSO, responseType, function (err, result) {
if (err) {
return sendResponse(undefined, err);
} else {
// Should we handle this differently as undefined typically means the model doesn't exist
return sendResponse(undefined, _.isUndefined(result) ?
stubResponse :
JSON.stringify(getMockValue(version, result)));
}
});
}
if (_.isUndefined(composedModel)) {
response = stubResponse;
} else {
response = JSON.stringify(getMockValue(version, composedModel));
return sendResponse(undefined, JSON.stringify(getMockValue(version, responseType.schema)));
}
} else {
// This is a primitive (Only possible in 1.2)
response = getMockValue(version, operation);
return sendResponse(undefined, getMockValue(version, responseType));
}
return response;
};

@@ -312,3 +310,3 @@

module.exports.createStubHandler = function createStubHandler (req, res, version) {
module.exports.createStubHandler = function createStubHandler (version, req, res, next, handlerName) {
// TODO: Handle headers for 2.0

@@ -318,9 +316,8 @@ // TODO: Handle examples (per mime-type) for 2.0

return function stubHandler (req, res) {
res.end(mockResponse(version, req));
// res.end('Stubbed response for ' + getHandlerName(version, req));
return function stubHandler () {
mockResponse(version, req, res, next, handlerName);
};
};
module.exports.isModelParameter = function isModelParameter (version, param) {
var isModelParameter = module.exports.isModelParameter = function isModelParameter (version, param) {
var spec = helpers.getSpec(version);

@@ -331,11 +328,14 @@ var isModel = false;

case '1.2':
if (!_.isUndefined(param.type) && spec.primitives.indexOf(param.type) === -1) {
if (!_.isUndefined(spec, param.type) && isModelType(spec, param.type)) {
isModel = true;
} else if (param.type === 'array' && !_.isUndefined(param.items.$ref)) {
} 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') {
if (param.type === 'object' || !param.type) {
isModel = true;

@@ -346,3 +346,3 @@ } else if (!_.isUndefined(param.schema) && (param.schema.type === 'object' || !_.isUndefined(param.schema.$ref))) {

// 2.0 does not allow arrays of models
// 2.0 does not allow arrays of models in the same way Swagger 1.2 does

@@ -355,5 +355,98 @@ break;

module.exports.getParameterValue = function getParameterValue (version, parameter, pathKeys, match, req) {
var defaultVal = version === '1.2' ? parameter.defaultValue : parameter.default;
var paramType = version === '1.2' ? parameter.paramType : parameter.in;
var val;
// Get the value to validate based on the operation parameter type
switch (paramType) {
case 'body':
case 'form':
if (!req.body) {
throw new Error('Server configuration error: req.body is not defined but is required');
}
if (isModelParameter(version, parameter)) {
val = req.body;
} else {
val = req.body[parameter.name];
}
break;
case 'header':
val = req.headers[parameter.name.toLowerCase()];
break;
case 'path':
_.each(pathKeys, function (key, index) {
if (key.name === parameter.name) {
val = match[index + 1];
}
});
break;
case 'query':
if (!req.query) {
throw new Error('Server configuration error: req.query is not defined but is required');
}
val = req.query[parameter.name];
break;
}
// Use the default value when necessary
if (_.isUndefined(val) && !_.isUndefined(defaultVal)) {
val = defaultVal;
}
return val;
};
module.exports.send400 = function send400 (req, res, next, err) {
var validationMessage;
res.statusCode = 400;
// Format the errors to include the parameter information
if (err.failedValidation === true) {
validationMessage = 'Parameter (' + err.paramName + ') ';
switch (err.code) {
case 'ENUM_MISMATCH':
case 'MAXIMUM':
case 'MAXIMUM_EXCLUSIVE':
case 'MINIMUM':
case 'MINIMUM_EXCLUSIVE':
case 'MULTIPLE_OF':
case 'INVALID_TYPE':
if (err.code === 'INVALID_TYPE' && err.message.split(' ')[0] === 'Value') {
validationMessage += err.message.split(' ').slice(1).join(' ');
} else {
validationMessage += 'is ' + err.message.charAt(0).toLowerCase() + err.message.substring(1);
}
break;
case 'ARRAY_LENGTH_LONG':
case 'ARRAY_LENGTH_SHORT':
case 'MAX_LENGTH':
case 'MIN_LENGTH':
validationMessage += err.message.split(' ').slice(1).join(' ');
break;
case 'MAX_PROPERTIES':
case 'MIN_PROPERTIES':
validationMessage += 'properties are ' + err.message.split(' ').slice(4).join(' ');
break;
default:
validationMessage += err.message.charAt(0).toLowerCase() + err.message.substring(1);
}
err.message = validationMessage;
}
return next(err);

@@ -360,0 +453,0 @@ };

// swagger-client.js
// version 2.1.0-alpha.2
// version 2.1.0-alpha.4
/**

@@ -90,11 +90,16 @@ * Array Model

else {
for(name in authorizations) {
for (key in this.authz) {
if(key == name) {
value = this.authz[key];
result = value.apply(obj, authorizations);
if (result === true)
status = true;
if(Array.isArray(authorizations)) {
var i;
for(i = 0; i < authorizations.length; i++) {
var auth = authorizations[i];
log(auth);
for (key in this.authz) {
var value = this.authz[key];
if(typeof value !== 'undefined') {
result = value.apply(obj, authorizations);
if (result === true)
status = true;
}
}
}
}
}

@@ -386,4 +391,7 @@ }

this.produces = response.produces;
this.authSchemes = response.authorizations;
this.securityDefinitions = response.securityDefinitions;
// legacy support
this.authSchemes = response.securityDefinitions;
var location = this.parseUri(this.url);

@@ -420,2 +428,5 @@ if(typeof this.schemes === 'undefined' || this.schemes.length === 0) {

for(httpMethod in response.paths[path]) {
if(['delete', 'get', 'head', 'options', 'patch', 'post', 'put'].indexOf(httpMethod) === -1) {
continue;
}
var operation = response.paths[path][httpMethod];

@@ -508,3 +519,7 @@ var tags = operation.tags;

else {
return path.substring(1).replace(/\//g, "_").replace(/\{/g, "").replace(/\}/g, "") + "_" + httpMethod;
return path.substring(1)
.replace(/\//g, "_")
.replace(/\{/g, "")
.replace(/\}/g, "")
.replace(/\./g, "_") + "_" + httpMethod;
}

@@ -547,2 +562,3 @@ }

this.security = args.security;
this.authorizations = args.security;
this.description = args.description;

@@ -558,3 +574,3 @@

var innerType = this.getType(param);
if(innerType.toString().toLowerCase() === 'boolean') {
if(innerType && innerType.toString().toLowerCase() === 'boolean') {
param.allowableValues = {};

@@ -655,4 +671,4 @@ param.isList = true;

str = 'long';
else if(type === 'integer' && typeof format === 'undefined')
str = 'long';
else if(type === 'integer')
str = 'integer'
else if(type === 'string' && format === 'date-time')

@@ -666,3 +682,3 @@ str = 'date-time';

str = 'double';
else if(type === 'number' && typeof format === 'undefined')
else if(type === 'number')
str = 'double';

@@ -839,3 +855,3 @@ else if(type === 'boolean')

}
else if (param.in === 'query') {
else if (param.in === 'query' && typeof args[param.name] !== 'undefined') {
if(querystring === '')

@@ -878,4 +894,9 @@ querystring += '?';

}
var url = this.scheme + '://' + this.host + this.basePath + requestUrl + querystring;
var url = this.scheme + '://' + this.host;
if(this.basePath !== '/')
url += this.basePath;
url += requestUrl + querystring;
var obj = {

@@ -928,3 +949,3 @@ url: url,

// if there's a body, need to set the accepts header via requestContentType
if (body && (this.type === 'post' || this.type === 'put' || this.type === 'patch' || this.type === 'delete')) {
if (body && (this.method === 'post' || this.method === 'put' || this.method === 'patch' || this.method === 'delete')) {
if (opts.requestContentType)

@@ -1105,10 +1126,7 @@ consumes = opts.requestContentType;

this.required = required;
if(obj['$ref']) {
var refType = obj['$ref'];
refType = refType.indexOf('#/definitions') === -1 ? refType : refType.substring('#/definitions').length;
this['$ref'] = refType;
}
if(obj['$ref'])
this['$ref'] = simpleRef(obj['$ref']);
else if (obj.type === 'array') {
if(obj.items['$ref'])
this['$ref'] = obj.items['$ref'];
this['$ref'] = simpleRef(obj.items['$ref']);
else

@@ -1144,3 +1162,4 @@ obj = obj.items;

if(this['$ref']) {
var refModel = models[this['$ref']];
var refModelName = simpleRef(this['$ref']);
var refModel = models[refModelName];
if(refModel && typeof ignoredModels[type] === 'undefined') {

@@ -1204,4 +1223,6 @@ ignoredModels[type] = this;

str += 'boolean';
else if(obj['$ref'])
str += simpleRef(obj['$ref']);
else
str += obj.type || obj['$ref'];
str += obj.type;
if(obj.type === 'array')

@@ -1213,2 +1234,4 @@ str += ']';

simpleRef = function(name) {
if(typeof name === 'undefined')
return null;
if(name.indexOf("#/definitions/") === 0)

@@ -1345,3 +1368,3 @@ return name.substring('#/definitions/'.length)

var headers = {},
headerArray = response.getAllResponseHeaders().split("\n");
headerArray = response.getAllResponseHeaders().split("\n");

@@ -1359,3 +1382,3 @@ for(var i = 0; i < headerArray.length; i++) {

var name = toSplit.substring(0, separator).trim(),
value = toSplit.substring(separator + 1).trim();
value = toSplit.substring(separator + 1).trim();
headers[name] = value;

@@ -1376,4 +1399,11 @@ }

if(contentType.indexOf("application/json") == 0 || contentType.indexOf("+json") > 0) {
if(response.responseText && response.responseText !== "")
out.obj = JSON.parse(response.responseText);
if(response.responseText && response.responseText !== "") {
try {
out.obj = JSON.parse(response.content.data);
}
catch (ex) {
// do not set out.obj
log ("unable to parse JSON content");
}
}
else

@@ -1380,0 +1410,0 @@ out.obj = {}

@@ -10,6 +10,25 @@ var appName;

if(window.swaggerUi.api.authSchemes
&& window.swaggerUi.api.authSchemes.oauth2
&& window.swaggerUi.api.authSchemes.oauth2.scopes) {
scopes = window.swaggerUi.api.authSchemes.oauth2.scopes;
var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions;
if(auths) {
var key;
var defs = auths;
for(key in defs) {
var auth = defs[key];
if(auth.type === 'oauth2' && auth.scopes) {
var scope;
if(Array.isArray(auth.scopes)) {
// 1.2 support
var i;
for(i = 0; i < auth.scopes.length; i++) {
scopes.push(auth.scopes[i]);
}
}
else {
// 2.0 support
for(scope in auth.scopes) {
scopes.push({scope: scope, description: auth.scopes[scope]});
}
}
}
}
}

@@ -22,32 +41,28 @@

if(popupDialog.length > 0)
popupDialog = popupDialog.last();
else {
popupDialog = $(
[
'<div class="api-popup-dialog">',
'<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
'<div class="api-popup-content">',
'<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
'<a href="#">Learn how to use</a>',
'</p>',
'<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
'<ul class="api-popup-scopes">',
'</ul>',
'<p class="error-msg"></p>',
'<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
'</div>',
'</div>'].join(''));
$(document.body).append(popupDialog);
popupDialog = $(
[
'<div class="api-popup-dialog">',
'<div class="api-popup-title">Select OAuth2.0 Scopes</div>',
'<div class="api-popup-content">',
'<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.',
'<a href="#">Learn how to use</a>',
'</p>',
'<p><strong>' + appName + '</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>',
'<ul class="api-popup-scopes">',
'</ul>',
'<p class="error-msg"></p>',
'<div class="api-popup-actions"><button class="api-popup-authbtn api-button green" type="button">Authorize</button><button class="api-popup-cancel api-button gray" type="button">Cancel</button></div>',
'</div>',
'</div>'].join(''));
$(document.body).append(popupDialog);
popup = popupDialog.find('ul.api-popup-scopes').empty();
for (i = 0; i < scopes.length; i ++) {
scope = scopes[i];
str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"/>' + '<label for="scope_' + i + '">' + scope.scope;
if (scope.description) {
str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
}
str += '</label></li>';
popup.append(str);
popup = popupDialog.find('ul.api-popup-scopes').empty();
for (i = 0; i < scopes.length; i ++) {
scope = scopes[i];
str = '<li><input type="checkbox" id="scope_' + i + '" scope="' + scope.scope + '"/>' + '<label for="scope_' + i + '">' + scope.scope;
if (scope.description) {
str += '<br/><span class="api-scope-desc">' + scope.description + '</span>';
}
str += '</label></li>';
popup.append(str);
}

@@ -72,3 +87,6 @@

popupDialog.hide();
popupDialog.empty();
popupDialog = [];
});
popupDialog.find('button.api-popup-authbtn').click(function() {

@@ -81,3 +99,3 @@ popupMask.hide();

var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/"));
var redirectUrl = host.protocol + '//' + host.host + pathname + "/o2c.html";
var redirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';
var url = null;

@@ -87,8 +105,17 @@

if (authSchemes.hasOwnProperty(key)) {
var o = authSchemes[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
url = dets.loginEndpoint.url + "?response_type=token";
window.swaggerUi.tokenName = dets.tokenName;
if(authSchemes[key].type === 'oauth2' && authSchemes[key].flow === 'implicit') {
var dets = authSchemes[key];
url = dets.authorizationUrl + '?response_type=token';
window.swaggerUi.tokenName = dets.tokenUrl || 'access_token';
}
else if(authSchemes[key].grantTypes) {
// 1.2 support
var o = authSchemes[key].grantTypes;
for(var t in o) {
if(o.hasOwnProperty(t) && t === 'implicit') {
var dets = o[t];
var ep = dets.loginEndpoint.url;
url = dets.loginEndpoint.url + '?response_type=token';
window.swaggerUi.tokenName = dets.tokenName;
}
}

@@ -102,3 +129,3 @@ }

for(k =0; k < o.length; k++) {
scopes.push($(o[k]).attr("scope"));
scopes.push($(o[k]).attr('scope'));
}

@@ -139,10 +166,10 @@

appName = (o.appName||errors.push("missing appName"));
appName = (o.appName||errors.push('missing appName'));
popupMask = (o.popupMask||$('#api-common-mask'));
popupDialog = (o.popupDialog||$('.api-popup-dialog'));
clientId = (o.clientId||errors.push("missing client id"));
realm = (o.realm||errors.push("missing realm"));
clientId = (o.clientId||errors.push('missing client id'));
realm = (o.realm||errors.push('missing realm'));
if(errors.length > 0){
log("auth unable initialize oauth: " + errors);
log('auth unable initialize oauth: ' + errors);
return;

@@ -213,4 +240,3 @@ }

});
window.authorizations.add("oauth2", new ApiKeyAuthorization("Authorization", "Bearer " + b, "header"));
window.authorizations.add('oauth2', new ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header'));
}

@@ -217,0 +243,0 @@ }

// swagger.js
// version 2.0.41
// version 2.0.47

@@ -142,3 +142,3 @@ (function () {

headers: {
accept: "application/json,application/json;charset=\"utf-8\",*/*"
accept: "application/json,application/json;charset=utf-8,*/*"
},

@@ -377,3 +377,3 @@ on: {

headers: {
accept: "application/json,application/json;charset=\"utf-8\",*/*"
accept: "application/json,application/json;charset=utf-8,*/*"
},

@@ -503,3 +503,3 @@ on: {

o.nickname = this.sanitize(o.nickname);
var op = new SwaggerOperation(o.nickname, resource_path, method, o.parameters, o.summary, o.notes, type, responseMessages, this, consumes, produces, o.authorizations);
var op = new SwaggerOperation(o.nickname, resource_path, method, o.parameters, o.summary, o.notes, type, responseMessages, this, consumes, produces, o.authorizations, o.deprecated);
this.operations[op.nickname] = op;

@@ -697,3 +697,3 @@ output.push(this.operationsArray.push(op));

var SwaggerOperation = function (nickname, path, method, parameters, summary, notes, type, responseMessages, resource, consumes, produces, authorizations) {
var SwaggerOperation = function (nickname, path, method, parameters, summary, notes, type, responseMessages, resource, consumes, produces, authorizations, deprecated) {
var _this = this;

@@ -714,2 +714,3 @@

this.authorizations = authorizations;
this.deprecated = deprecated;
this["do"] = __bind(this["do"], this);

@@ -746,3 +747,3 @@

if (type.toLowerCase() === 'boolean') {
if (type && type.toLowerCase() === 'boolean') {
param.allowableValues = {};

@@ -913,2 +914,8 @@ param.allowableValues.values = ["true", "false"];

possibleParams.push(param);
else if (param.paramType === 'body' && param.name !== 'body') {
if (args.body) {
throw new Error("Saw two body params in an API listing; expecting a max of one.");
}
args.body = args[param.name];
}
}

@@ -971,3 +978,3 @@

// apply path params and remove from args
var reg = new RegExp('\\{\\s*?' + param.name + '.*?\\}(?=\\s*?(\\/|$))', 'gi');
var reg = new RegExp('\\{\\s*?' + param.name + '.*?\\}(?=\\s*?(\\/?|$))', 'gi');
url = url.replace(reg, this.encodePathParam(args[param.name]));

@@ -984,20 +991,22 @@ delete args[param.name];

var param = params[i];
if (param.paramType === 'query') {
if (args[param.name] !== undefined) {
var value = args[param.name];
if (queryParams !== '')
queryParams += '&';
if (Array.isArray(value)) {
var j;
var output = '';
for(j = 0; j < value.length; j++) {
if(j > 0)
output += ',';
output += encodeURIComponent(value[j]);
}
queryParams += encodeURIComponent(param.name) + '=' + output;
if(param.paramType === 'query') {
if (queryParams !== '')
queryParams += '&';
if (Array.isArray(param)) {
var j;
var output = '';
for(j = 0; j < param.length; j++) {
if(j > 0)
output += ',';
output += encodeURIComponent(param[j]);
}
queryParams += encodeURIComponent(param.name) + '=' + output;
}
else {
if (args[param.name]) {
queryParams += encodeURIComponent(param.name) + '=' + encodeURIComponent(args[param.name]);
} else {
if (param.required)
throw "" + param.name + " is a required query param.";
}
else {
queryParams += encodeURIComponent(param.name) + '=' + encodeURIComponent(args[param.name]);
}
}

@@ -1283,3 +1292,3 @@ }

else if (this.type != "DELETE")
accepts = null;
consumes = null;
}

@@ -1502,8 +1511,14 @@

var contentType = (response._headers["content-type"] || response._headers["Content-Type"] || null)
var headers = response._headers.normalized || response._headers;
var contentType = (headers["content-type"] || headers["Content-Type"] || null)
if (contentType != null) {
if (contentType.indexOf("application/json") == 0 || contentType.indexOf("+json") > 0) {
if (response.content.data && response.content.data !== "")
out.obj = JSON.parse(response.content.data);
try {
out.obj = JSON.parse(response.content.data);
}
catch (ex) {
// do not set out.obj
log ("unable to parse JSON content");
}
else

@@ -1673,2 +1688,4 @@ out.obj = {}

e.parameterMacro = parameterMacro;
e.modelPropertyMacro = modelPropertyMacro;
e.SampleModels = sampleModels;

@@ -1675,0 +1692,0 @@ e.SwaggerHttp = SwaggerHttp;

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

$(function(){$.fn.vAlign=function(){return this.each(function(c){var a=$(this).height();var d=$(this).parent().height();var b=(d-a)/2;$(this).css("margin-top",b)})};$.fn.stretchFormtasticInputWidthToParent=function(){return this.each(function(b){var d=$(this).closest("form").innerWidth();var c=parseInt($(this).closest("form").css("padding-left"),10)+parseInt($(this).closest("form").css("padding-right"),10);var a=parseInt($(this).css("padding-left"),10)+parseInt($(this).css("padding-right"),10);$(this).css("width",d-c-a)})};$("form.formtastic li.string input, form.formtastic textarea").stretchFormtasticInputWidthToParent();$("ul.downplayed li div.content p").vAlign();$("form.sandbox").submit(function(){var a=true;$(this).find("input.required").each(function(){$(this).removeClass("error");if($(this).val()==""){$(this).addClass("error");$(this).wiggle();a=false}});return a})});function clippyCopiedCallback(b){$("#api_key_copied").fadeIn().delay(1000).fadeOut()}log=function(){log.history=log.history||[];log.history.push(arguments);if(this.console){console.log(Array.prototype.slice.call(arguments)[0])}};if(Function.prototype.bind&&console&&typeof console.log=="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(a){console[a]=this.bind(console[a],console)},Function.prototype.call)}var Docs={shebang:function(){var b=$.param.fragment().split("/");b.shift();switch(b.length){case 1:var d="resource_"+b[0];Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});break;case 2:Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});var c=b.join("_");var a=c+"_content";Docs.expandOperation($("#"+a));$("#"+c).slideto({highlight:false});break}},toggleEndpointListForResource:function(b){var a=$("li#resource_"+Docs.escapeResourceName(b)+" ul.endpoints");if(a.is(":visible")){Docs.collapseEndpointListForResource(b)}else{Docs.expandEndpointListForResource(b)}},expandEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);if(b==""){$(".resource ul.endpoints").slideDown();return}$("li#resource_"+b).addClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideDown()},collapseEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);$("li#resource_"+b).removeClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideUp()},expandOperationsForResource:function(a){Docs.expandEndpointListForResource(a);if(a==""){$(".resource ul.endpoints li.operation div.content").slideDown();return}$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.expandOperation($(this))})},collapseOperationsForResource:function(a){Docs.expandEndpointListForResource(a);$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.collapseOperation($(this))})},escapeResourceName:function(a){return a.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]\^`{|}~]/g,"\\$&")},expandOperation:function(a){a.slideDown()},collapseOperation:function(a){a.slideUp()}};(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="contentType"></label>\n<select name="contentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.main=b(function(h,n,g,m,l){this.compilerInfo=[4,">= 1.0.0"];g=this.merge(g,h.helpers);l=l||{};var j="",c,s,i="function",k=this.escapeExpression,q=this;function f(x,w){var t="",v,u;t+='\n <div class="info_title">'+k(((v=((v=x.info),v==null||v===false?v:v.title)),typeof v===i?v.apply(x):v))+'</div>\n <div class="info_description">';u=((v=((v=x.info),v==null||v===false?v:v.description)),typeof v===i?v.apply(x):v);if(u||u===0){t+=u}t+="</div>\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.termsOfServiceUrl),{hash:{},inverse:q.noop,fn:q.program(2,d,w),data:w});if(u||u===0){t+=u}t+="\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.contact),{hash:{},inverse:q.noop,fn:q.program(4,r,w),data:w});if(u||u===0){t+=u}t+="\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.license),{hash:{},inverse:q.noop,fn:q.program(6,p,w),data:w});if(u||u===0){t+=u}t+="\n ";return t}function d(w,v){var t="",u;t+='<div class="info_tos"><a href="'+k(((u=((u=w.info),u==null||u===false?u:u.termsOfServiceUrl)),typeof u===i?u.apply(w):u))+'">Terms of service</a></div>';return t}function r(w,v){var t="",u;t+="<div class='info_contact'><a href=\"mailto:"+k(((u=((u=((u=w.info),u==null||u===false?u:u.contact)),u==null||u===false?u:u.name)),typeof u===i?u.apply(w):u))+'">Contact the developer</a></div>';return t}function p(w,v){var t="",u;t+="<div class='info_license'><a href='"+k(((u=((u=((u=w.info),u==null||u===false?u:u.license)),u==null||u===false?u:u.url)),typeof u===i?u.apply(w):u))+"'>"+k(((u=((u=((u=w.info),u==null||u===false?u:u.license)),u==null||u===false?u:u.name)),typeof u===i?u.apply(w):u))+"</a></div>";return t}function o(w,v){var t="",u;t+='\n , <span style="font-variant: small-caps">api version</span>: '+k(((u=((u=w.info),u==null||u===false?u:u.version)),typeof u===i?u.apply(w):u))+"\n ";return t}function e(w,v){var t="",u;t+='\n <span style="float:right"><a href="';if(u=g.validatorUrl){u=u.call(w,{hash:{},data:v})}else{u=w.validatorUrl;u=typeof u===i?u.apply(w):u}t+=k(u)+"/debug?url=";if(u=g.url){u=u.call(w,{hash:{},data:v})}else{u=w.url;u=typeof u===i?u.apply(w):u}t+=k(u)+'"><img id="validator" src="';if(u=g.validatorUrl){u=u.call(w,{hash:{},data:v})}else{u=w.validatorUrl;u=typeof u===i?u.apply(w):u}t+=k(u)+"?url=";if(u=g.url){u=u.call(w,{hash:{},data:v})}else{u=w.url;u=typeof u===i?u.apply(w):u}t+=k(u)+'"></a>\n </span>\n ';return t}j+="<div class='info' id='api_info'>\n ";c=g["if"].call(n,n.info,{hash:{},inverse:q.noop,fn:q.program(1,f,l),data:l});if(c||c===0){j+=c}j+="\n</div>\n<div class='container' id='resources_container'>\n <ul id='resources'>\n </ul>\n\n <div class=\"footer\">\n <br>\n <br>\n <h4 style=\"color: #999\">[ <span style=\"font-variant: small-caps\">base url</span>: ";if(c=g.basePath){c=c.call(n,{hash:{},data:l})}else{c=n.basePath;c=typeof c===i?c.apply(n):c}j+=k(c)+"\n ";s=g["if"].call(n,((c=n.info),c==null||c===false?c:c.version),{hash:{},inverse:q.noop,fn:q.program(8,o,l),data:l});if(s||s===0){j+=s}j+="]\n ";s=g["if"].call(n,n.validatorUrl,{hash:{},inverse:q.noop,fn:q.program(10,e,l),data:l});if(s||s===0){j+=s}j+="\n </h4>\n </div>\n</div>\n";return j})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.operation=b(function(j,u,s,o,A){this.compilerInfo=[4,">= 1.0.0"];s=this.merge(s,j.helpers);A=A||{};var t="",k,f,e="function",d=this.escapeExpression,r=this,c=s.blockHelperMissing;function q(C,B){return"deprecated"}function p(C,B){return"\n <h4>Warning: Deprecated</h4>\n "}function n(E,D){var B="",C;B+="\n <h4>Implementation Notes</h4>\n <p>";if(C=s.description){C=C.call(E,{hash:{},data:D})}else{C=E.description;C=typeof C===e?C.apply(E):C}if(C||C===0){B+=C}B+="</p>\n ";return B}function m(C,B){return'\n <div class="auth">\n <span class="api-ic ic-error"></span>'}function i(E,D){var B="",C;B+='\n <div id="api_information_panel" style="top: 526px; left: 776px; display: none;">\n ';C=s.each.call(E,E,{hash:{},inverse:r.noop,fn:r.program(10,z,D),data:D});if(C||C===0){B+=C}B+="\n </div>\n ";return B}function z(F,E){var B="",D,C;B+="\n <div title='";C=((D=F.description),typeof D===e?D.apply(F):D);if(C||C===0){B+=C}B+="'>"+d(((D=F.scope),typeof D===e?D.apply(F):D))+"</div>\n ";return B}function y(C,B){return"</div>"}function x(C,B){return'\n <div class=\'access\'>\n <span class="api-ic ic-off" title="click to authenticate"></span>\n </div>\n '}function w(C,B){return'\n <h4>Response Class</h4>\n <p><span class="model-signature" /></p>\n <br/>\n <div class="response-content-type" />\n '}function v(C,B){return'\n <h4>Parameters</h4>\n <table class=\'fullwidth\'>\n <thead>\n <tr>\n <th style="width: 100px; max-width: 100px">Parameter</th>\n <th style="width: 310px; max-width: 310px">Value</th>\n <th style="width: 200px; max-width: 200px">Description</th>\n <th style="width: 100px; max-width: 100px">Parameter Type</th>\n <th style="width: 220px; max-width: 230px">Data Type</th>\n </tr>\n </thead>\n <tbody class="operation-params">\n\n </tbody>\n </table>\n '}function l(C,B){return"\n <div style='margin:0;padding:0;display:inline'></div>\n <h4>Response Messages</h4>\n <table class='fullwidth'>\n <thead>\n <tr>\n <th>HTTP Status Code</th>\n <th>Reason</th>\n <th>Response Model</th>\n </tr>\n </thead>\n <tbody class=\"operation-status\">\n \n </tbody>\n </table>\n "}function h(C,B){return"\n "}function g(C,B){return"\n <div class='sandbox_header'>\n <input class='submit' name='commit' type='button' value='Try it out!' />\n <a href='#' class='response_hider' style='display:none'>Hide Response</a>\n <span class='response_throbber' style='display:none'></span>\n </div>\n "}t+="\n <ul class='operations' >\n <li class='";if(k=s.method){k=k.call(u,{hash:{},data:A})}else{k=u.method;k=typeof k===e?k.apply(u):k}t+=d(k)+" operation' id='";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"_";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"'>\n <div class='heading'>\n <h3>\n <span class='http_method'>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+'\' class="toggleOperation">';if(k=s.method){k=k.call(u,{hash:{},data:A})}else{k=u.method;k=typeof k===e?k.apply(u):k}t+=d(k)+"</a>\n </span>\n <span class='path'>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"' class=\"toggleOperation ";k=s["if"].call(u,u.deprecated,{hash:{},inverse:r.noop,fn:r.program(1,q,A),data:A});if(k||k===0){t+=k}t+='">';if(k=s.path){k=k.call(u,{hash:{},data:A})}else{k=u.path;k=typeof k===e?k.apply(u):k}t+=d(k)+"</a>\n </span>\n </h3>\n <ul class='options'>\n <li>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+'\' class="toggleOperation">';if(k=s.summary){k=k.call(u,{hash:{},data:A})}else{k=u.summary;k=typeof k===e?k.apply(u):k}if(k||k===0){t+=k}t+="</a>\n </li>\n </ul>\n </div>\n <div class='content' id='";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"_";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"_content' style='display:none'>\n ";k=s["if"].call(u,u.deprecated,{hash:{},inverse:r.noop,fn:r.program(3,p,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.description,{hash:{},inverse:r.noop,fn:r.program(5,n,A),data:A});if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(7,m,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";k=s.each.call(u,u.oauth,{hash:{},inverse:r.noop,fn:r.program(9,i,A),data:A});if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(12,y,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(14,x,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.type,{hash:{},inverse:r.noop,fn:r.program(16,w,A),data:A});if(k||k===0){t+=k}t+="\n <form accept-charset='UTF-8' class='sandbox'>\n <div style='margin:0;padding:0;display:inline'></div>\n ";k=s["if"].call(u,u.parameters,{hash:{},inverse:r.noop,fn:r.program(18,v,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.responseMessages,{hash:{},inverse:r.noop,fn:r.program(20,l,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.isReadOnly,{hash:{},inverse:r.program(24,g,A),fn:r.program(22,h,A),data:A});if(k||k===0){t+=k}t+="\n </form>\n <div class='response' style='display:none'>\n <h4>Request URL</h4>\n <div class='block request_url'></div>\n <h4>Response Body</h4>\n <div class='block response_body'></div>\n <h4>Response Code</h4>\n <div class='block response_code'></div>\n <h4>Response Headers</h4>\n <div class='block response_headers'></div>\n </div>\n </div>\n </li>\n </ul>\n";return t})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param=b(function(f,q,o,j,t){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);t=t||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(4,k,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function l(y,x){var v="",w;v+='\n <input type="file" name=\'';if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'/>\n <div class="parameter-content-type" />\n ';return v}function k(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y["default"],{hash:{},inverse:n.program(7,h,x),fn:n.program(5,i,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function i(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"'>";if(w=o["default"]){w=w.call(y,{hash:{},data:x})}else{w=y["default"];w=typeof w===d?w.apply(y):w}v+=c(w)+"</textarea>\n ";return v}function h(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return v}function e(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(10,u,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function u(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y["default"],{hash:{},inverse:n.program(13,r,x),fn:n.program(11,s,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function s(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value='";if(w=o["default"]){w=w.call(y,{hash:{},data:x})}else{w=y["default"];w=typeof w===d?w.apply(y):w}v+=c(w)+"'/>\n ";return v}function r(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value=''/>\n ";return v}p+="<td class='code'>";if(g=o.name){g=g.call(q,{hash:{},data:t})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,t),fn:n.program(1,m,t),data:t});if(g||g===0){p+=g}p+="\n\n</td>\n<td>";if(g=o.description){g=g.call(q,{hash:{},data:t})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:t})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td>\n <span class="model-signature"></span>\n</td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_list=b(function(h,t,r,m,y){this.compilerInfo=[4,">= 1.0.0"];r=this.merge(r,h.helpers);y=y||{};var s="",j,g,e,p=this,q=r.helperMissing,d="function",c=this.escapeExpression;function o(A,z){return" multiple='multiple'"}function n(A,z){return"\n "}function l(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C.defaultValue,{hash:{},inverse:p.program(8,i,B),fn:p.program(6,k,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function k(A,z){return"\n "}function i(E,D){var z="",C,B,A;z+="\n ";A={hash:{},inverse:p.program(11,x,D),fn:p.program(9,f,D),data:D};B=((C=r.isArray||E.isArray),C?C.call(E,E,A):q.call(E,"isArray",E,A));if(B||B===0){z+=B}z+="\n ";return z}function f(A,z){return"\n "}function x(A,z){return"\n <option selected=\"\" value=''></option>\n "}function w(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C.isDefault,{hash:{},inverse:p.program(16,u,B),fn:p.program(14,v,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function v(C,B){var z="",A;z+='\n <option selected="" value=\'';if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+" (default)</option>\n ";return z}function u(C,B){var z="",A;z+="\n <option value='";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"</option>\n ";return z}s+="<td class='code'>";if(j=r.name){j=j.call(t,{hash:{},data:y})}else{j=t.name;j=typeof j===d?j.apply(t):j}s+=c(j)+"</td>\n<td>\n <select ";e={hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y};g=((j=r.isArray||t.isArray),j?j.call(t,t,e):q.call(t,"isArray",t,e));if(g||g===0){s+=g}s+=" class='parameter' name='";if(g=r.name){g=g.call(t,{hash:{},data:y})}else{g=t.name;g=typeof g===d?g.apply(t):g}s+=c(g)+"'>\n ";g=r["if"].call(t,t.required,{hash:{},inverse:p.program(5,l,y),fn:p.program(3,n,y),data:y});if(g||g===0){s+=g}s+="\n ";g=r.each.call(t,((j=t.allowableValues),j==null||j===false?j:j.descriptiveValues),{hash:{},inverse:p.noop,fn:p.program(13,w,y),data:y});if(g||g===0){s+=g}s+="\n </select>\n</td>\n<td>";if(g=r.description){g=g.call(t,{hash:{},data:y})}else{g=t.description;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+="</td>\n<td>";if(g=r.paramType){g=g.call(t,{hash:{},data:y})}else{g=t.paramType;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+='</td>\n<td><span class="model-signature"></span></td>';return s})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t.defaultValue,{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly_required=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' placeholder='(required)' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t.defaultValue,{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f.defaultValue){r=r.call(t,{hash:{},data:s})}else{r=t.defaultValue;r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code required'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_required=b(function(f,q,o,j,u){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);u=u||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(4,k,y),fn:n.program(2,l,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function l(z,y){var w="",x;w+='\n <input type="file" name=\'';if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function k(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.defaultValue,{hash:{},inverse:n.program(7,h,y),fn:n.program(5,i,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function i(z,y){var w="",x;w+="\n <textarea class='body-textarea' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'>";if(x=o.defaultValue){x=x.call(z,{hash:{},data:y})}else{x=z.defaultValue;x=typeof x===d?x.apply(z):x}w+=c(x)+"</textarea>\n ";return w}function h(z,y){var w="",x;w+="\n <textarea class='body-textarea' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return w}function e(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(12,t,y),fn:n.program(10,v,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function v(z,y){var w="",x;w+="\n <input class='parameter' class='required' type='file' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function t(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.defaultValue,{hash:{},inverse:n.program(15,r,y),fn:n.program(13,s,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function s(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value='";if(x=o.defaultValue){x=x.call(z,{hash:{},data:y})}else{x=z.defaultValue;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function r(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value=''/>\n ";return w}p+="<td class='code required'>";if(g=o.name){g=g.call(q,{hash:{},data:u})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,u),fn:n.program(1,m,u),data:u});if(g||g===0){p+=g}p+="\n</td>\n<td>\n <strong>";if(g=o.description){g=g.call(q,{hash:{},data:u})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</strong>\n</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:u})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td><span class="model-signature"></span></td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.parameter_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.consumes,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="parameterContentType"></label>\n<select name="parameterContentType">\n';c=f["if"].call(l,l.consumes,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.resource=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,p,h="function",j=this.escapeExpression,o=this,n=f.blockHelperMissing;function e(r,q){return" : "}function c(t,s){var q="",r;q+="<li>\n <a href='";if(r=f.url){r=r.call(t,{hash:{},data:s})}else{r=t.url;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>Raw</a>\n </li>";return q}i+="<div class='heading'>\n <h2>\n <a href='#!/";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'\' class="toggleEndpointList" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">';if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</a> ";p={hash:{},inverse:o.noop,fn:o.program(1,e,k),data:k};if(d=f.summary){d=d.call(m,p)}else{d=m.summary;d=typeof d===h?d.apply(m):d}if(!f.summary){d=n.call(m,d,p)}if(d||d===0){i+=d}if(d=f.summary){d=d.call(m,{hash:{},data:k})}else{d=m.summary;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="\n </h2>\n <ul class='options'>\n <li>\n <a href='#!/";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+"' id='endpointListTogger_";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'\' class="toggleEndpointList" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">Show/Hide</a>\n </li>\n <li>\n <a href=\'#\' class="collapseResource" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">\n List Operations\n </a>\n </li>\n <li>\n <a href=\'#\' class="expandResource" data-id=';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+">\n Expand Operations\n </a>\n </li>\n ";p={hash:{},inverse:o.noop,fn:o.program(3,c,k),data:k};if(d=f.url){d=d.call(m,p)}else{d=m.url;d=typeof d===h?d.apply(m):d}if(!f.url){d=n.call(m,d,p)}if(d||d===0){i+=d}i+="\n </ul>\n</div>\n<ul class='endpoints' id='";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+"_endpoint_list' style='display:none'>\n\n</ul>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.response_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="responseContentType"></label>\n<select name="responseContentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.signature=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+='<div>\n<ul class="signature-nav">\n <li><a class="description-link" href="#">Model</a></li>\n <li><a class="snippet-link" href="#">Model Schema</a></li>\n</ul>\n<div>\n\n<div class="signature-container">\n <div class="description">\n ';if(c=d.signature){c=c.call(k,{hash:{},data:i})}else{c=k.signature;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+='\n </div>\n\n <div class="snippet">\n <pre><code>';if(c=d.sampleJSON){c=c.call(k,{hash:{},data:i})}else{c=k.sampleJSON;c=typeof c===f?c.apply(k):c}g+=h(c)+'</code></pre>\n <small class="notice"></small>\n </div>\n</div>\n\n';return g})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.status_code=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+="<td width='15%' class='code'>";if(c=d.code){c=c.call(k,{hash:{},data:i})}else{c=k.code;c=typeof c===f?c.apply(k):c}g+=h(c)+"</td>\n<td>";if(c=d.message){c=c.call(k,{hash:{},data:i})}else{c=k.message;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+="</td>\n<td width='50%'><span class=\"model-signature\" /></td>";return g})})();(function(){var j,r,u,o,l,k,n,m,i,p,s,q,h,c,g,f,e,d,b,a,x,w,t={}.hasOwnProperty,v=function(B,z){for(var y in z){if(t.call(z,y)){B[y]=z[y]}}function A(){this.constructor=B}A.prototype=z.prototype;B.prototype=new A();B.__super__=z.prototype;return B};s=(function(z){v(y,z);function y(){q=y.__super__.constructor.apply(this,arguments);return q}y.prototype.dom_id="swagger_ui";y.prototype.options=null;y.prototype.api=null;y.prototype.headerView=null;y.prototype.mainView=null;y.prototype.initialize=function(A){var B=this;if(A==null){A={}}if(A.dom_id!=null){this.dom_id=A.dom_id;delete A.dom_id}if($("#"+this.dom_id)==null){$("body").append('<div id="'+this.dom_id+'"></div>')}this.options=A;this.options.success=function(){return B.render()};this.options.progress=function(C){return B.showMessage(C)};this.options.failure=function(C){if(B.api&&B.api.isValid===false){log("not a valid 2.0 spec, loading legacy client");B.api=new SwaggerApi(B.options);return B.api.build()}else{return B.onLoadFailure(C)}};this.headerView=new r({el:$("#header")});return this.headerView.on("update-swagger-ui",function(C){return B.updateSwaggerUi(C)})};y.prototype.setOption=function(A,B){return this.options[A]=B};y.prototype.getOption=function(A){return this.options[A]};y.prototype.updateSwaggerUi=function(A){this.options.url=A.url;return this.load()};y.prototype.load=function(){var B,A;if((A=this.mainView)!=null){A.clear()}B=this.options.url;if(B.indexOf("http")!==0){B=this.buildUrl(window.location.href.toString(),B)}this.options.url=B;this.headerView.update(B);this.api=new SwaggerClient(this.options);return this.api.build()};y.prototype.render=function(){var A=this;this.showMessage("Finished Loading Resource Information. Rendering Swagger UI...");this.mainView=new u({model:this.api,el:$("#"+this.dom_id),swaggerOptions:this.options}).render();this.showMessage();switch(this.options.docExpansion){case"full":Docs.expandOperationsForResource("");break;case"list":Docs.collapseOperationsForResource("")}if(this.options.onComplete){this.options.onComplete(this.api,this)}return setTimeout(function(){return Docs.shebang()},400)};y.prototype.buildUrl=function(C,A){var B,D;log("base is "+C);if(A.indexOf("/")===0){D=C.split("/");C=D[0]+"//"+D[2];return C+A}else{B=C.length;if(C.indexOf("?")>-1){B=Math.min(B,C.indexOf("?"))}if(C.indexOf("#")>-1){B=Math.min(B,C.indexOf("#"))}C=C.substring(0,B);if(C.indexOf("/",C.length-1)!==-1){return C+A}return C+"/"+A}};y.prototype.showMessage=function(A){if(A==null){A=""}$("#message-bar").removeClass("message-fail");$("#message-bar").addClass("message-success");return $("#message-bar").html(A)};y.prototype.onLoadFailure=function(A){var B;if(A==null){A=""}$("#message-bar").removeClass("message-success");$("#message-bar").addClass("message-fail");B=$("#message-bar").html(A);if(this.options.onFailure!=null){this.options.onFailure(A)}return B};return y})(Backbone.Router);window.SwaggerUi=s;r=(function(z){v(y,z);function y(){h=y.__super__.constructor.apply(this,arguments);return h}y.prototype.events={"click #show-pet-store-icon":"showPetStore","click #show-wordnik-dev-icon":"showWordnikDev","click #explore":"showCustom","keyup #input_baseUrl":"showCustomOnKeyup","keyup #input_apiKey":"showCustomOnKeyup"};y.prototype.initialize=function(){};y.prototype.showPetStore=function(A){return this.trigger("update-swagger-ui",{url:"http://petstore.swagger.wordnik.com/api/api-docs"})};y.prototype.showWordnikDev=function(A){return this.trigger("update-swagger-ui",{url:"http://api.wordnik.com/v4/resources.json"})};y.prototype.showCustomOnKeyup=function(A){if(A.keyCode===13){return this.showCustom()}};y.prototype.showCustom=function(A){if(A!=null){A.preventDefault()}return this.trigger("update-swagger-ui",{url:$("#input_baseUrl").val(),apiKey:$("#input_apiKey").val()})};y.prototype.update=function(B,C,A){if(A==null){A=false}$("#input_baseUrl").val(B);if(A){return this.trigger("update-swagger-ui",{url:B})}};return y})(Backbone.View);u=(function(y){var z;v(A,y);function A(){g=A.__super__.constructor.apply(this,arguments);return g}z={alpha:function(C,B){return C.path.localeCompare(B.path)},method:function(C,B){return C.method.localeCompare(B.method)}};A.prototype.initialize=function(B){var C,I,J,E,D,G,H,F;if(B==null){B={}}if(B.swaggerOptions.sorter){E=B.swaggerOptions.sorter;J=z[E];if(this.model.apisArray){F=this.model.apisArray;for(G=0,H=F.length;G<H;G++){I=F[G];I.operationsArray.sort(J)}if(E==="alpha"){this.model.apisArray.sort(J)}}}if(this.model.info&&this.model.info.license&&typeof this.model.info.license==="string"){C=this.model.info.license;D=this.model.info.licenseUrl;this.model.info.license={};this.model.info.license.name=C;this.model.info.license.url=D}if(!this.model.info){this.model.info={}}if(!this.model.info.version){this.model.info.version=this.model.apiVersion}if(this.model.swaggerVersion==="2.0"){if("validatorUrl" in B.swaggerOptions){return this.model.validatorUrl=B.swaggerOptions.validatorUrl}else{if(this.model.url.match(/https?:\/\/localhost/)){return this.model.validatorUrl=this.model.url}else{return this.model.validatorUrl="http://online.swagger.io/validator"}}}};A.prototype.render=function(){var C,H,E,F,D,B,G;$(this.el).html(Handlebars.templates.main(this.model));F={};C=0;G=this.model.apisArray;for(D=0,B=G.length;D<B;D++){E=G[D];H=E.name;while(typeof F[H]!=="undefined"){H=H+"_"+C;C+=1}E.id=H;F[H]=E;this.addResource(E)}return this};A.prototype.addResource=function(C){var B;C.id=C.id.replace(/\s/g,"_");B=new n({model:C,tagName:"li",id:"resource_"+C.id,className:"resource",swaggerOptions:this.options.swaggerOptions});return $("#resources").append(B.render().el)};A.prototype.clear=function(){return $(this.el).html("")};return A})(Backbone.View);n=(function(z){v(y,z);function y(){f=y.__super__.constructor.apply(this,arguments);return f}y.prototype.initialize=function(){if(""===this.model.description){return this.model.description=null}};y.prototype.render=function(){var B,G,D,C,E,A,F;$(this.el).html(Handlebars.templates.resource(this.model));D={};if(this.model.description){this.model.summary=this.model.description}F=this.model.operationsArray;for(E=0,A=F.length;E<A;E++){C=F[E];B=0;G=C.nickname;while(typeof D[G]!=="undefined"){G=G+"_"+B;B+=1}D[G]=C;C.nickname=G;C.parentId=this.model.id;this.addOperation(C)}$(".toggleEndpointList",this.el).click(this.callDocs.bind(this,"toggleEndpointListForResource"));$(".collapseResource",this.el).click(this.callDocs.bind(this,"collapseOperationsForResource"));$(".expandResource",this.el).click(this.callDocs.bind(this,"expandOperationsForResource"));return this};y.prototype.addOperation=function(A){var B;A.number=this.number;B=new o({model:A,tagName:"li",className:"endpoint",swaggerOptions:this.options.swaggerOptions});$(".endpoints",$(this.el)).append(B.render().el);return this.number++};y.prototype.callDocs=function(B,A){A.preventDefault();return Docs[B](A.currentTarget.getAttribute("data-id"))};return y})(Backbone.View);o=(function(z){v(y,z);function y(){e=y.__super__.constructor.apply(this,arguments);return e}y.prototype.invocationUrl=null;y.prototype.events={"submit .sandbox":"submitOperation","click .submit":"submitOperation","click .response_hider":"hideResponse","click .toggleOperation":"toggleOperationContent","mouseenter .api-ic":"mouseEnter","mouseout .api-ic":"mouseExit"};y.prototype.initialize=function(){};y.prototype.mouseEnter=function(F){var D,E,I,B,A,J,G,C,K,H;D=$(F.currentTarget.parentNode).find("#api_information_panel");K=F.pageX;H=F.pageY;J=$(window).scrollLeft();G=$(window).scrollTop();B=J+$(window).width();A=G+$(window).height();C=D.width();E=D.height();if(K+C>B){K=B-C}if(K<J){K=J}if(H+E>A){H=A-E}if(H<G){H=G}I={};I.top=H;I.left=K;D.css(I);return $(F.currentTarget.parentNode).find("#api_information_panel").show()};y.prototype.mouseExit=function(A){return $(A.currentTarget.parentNode).find("#api_information_panel").hide()};y.prototype.render=function(){var D,U,V,T,R,K,J,Q,L,P,W,O,M,I,N,S,H,G,F,C,Y,ab,Z,X,E,B,A,ac,aa;V=true;if(!V){this.model.isReadOnly=true}this.model.description=this.model.description||this.model.notes;if(this.model.description){this.model.description=this.model.description.replace(/(?:\r\n|\r|\n)/g,"<br />")}this.model.oauth=null;if(this.model.authorizations){E=this.model.authorizations;for(T in E){N=E[T];if(T==="oauth2"){if(this.model.oauth===null){this.model.oauth={}}if(this.model.oauth.scopes===void 0){this.model.oauth.scopes=[]}for(H=0,Y=N.length;H<Y;H++){R=N[H];this.model.oauth.scopes.push(R)}}}}if(typeof this.model.responses!=="undefined"){this.model.responseMessages=[];B=this.model.responses;for(D in B){S=B[D];P=null;W=this.model.responses[D].schema;if(W&&W["$ref"]){P=W["$ref"];if(P.indexOf("#/definitions/")===0){P=P.substring("#/definitions/".length)}}this.model.responseMessages.push({code:D,message:S.description,responseModel:P})}}if(typeof this.model.responseMessages==="undefined"){this.model.responseMessages=[]}$(this.el).html(Handlebars.templates.operation(this.model));if(this.model.responseClassSignature&&this.model.responseClassSignature!=="string"){O={sampleJSON:this.model.responseSampleJSON,isParam:false,signature:this.model.responseClassSignature};L=new i({model:O,tagName:"div"});$(".model-signature",$(this.el)).append(L.render().el)}else{this.model.responseClassSignature="string";$(".model-signature",$(this.el)).html(this.model.type)}U={isParam:false};U.consumes=this.model.consumes;U.produces=this.model.produces;A=this.model.parameters;for(G=0,ab=A.length;G<ab;G++){K=A[G];I=K.type||K.dataType;if(typeof I==="undefined"){P=K.schema;if(P&&P["$ref"]){J=P["$ref"];if(J.indexOf("#/definitions/")===0){I=J.substring("#/definitions/".length)}else{I=J}}}if(I&&I.toLowerCase()==="file"){if(!U.consumes){U.consumes="multipart/form-data"}}K.type=I}Q=new m({model:U});$(".response-content-type",$(this.el)).append(Q.render().el);ac=this.model.parameters;for(F=0,Z=ac.length;F<Z;F++){K=ac[F];this.addParameter(K,U.consumes)}aa=this.model.responseMessages;for(C=0,X=aa.length;C<X;C++){M=aa[C];this.addStatusCode(M)}return this};y.prototype.addParameter=function(C,A){var B;C.consumes=A;B=new k({model:C,tagName:"tr",readOnly:this.model.isReadOnly});return $(".operation-params",$(this.el)).append(B.render().el)};y.prototype.addStatusCode=function(B){var A;A=new p({model:B,tagName:"tr"});return $(".operation-status",$(this.el)).append(A.render().el)};y.prototype.submitOperation=function(O){var Q,G,N,D,I,A,J,M,L,K,P,F,C,H,E,B;if(O!=null){O.preventDefault()}G=$(".sandbox",$(this.el));Q=true;G.find("input.required").each(function(){var R=this;$(this).removeClass("error");if(jQuery.trim($(this).val())===""){$(this).addClass("error");$(this).wiggle({callback:function(){return $(R).focus()}});return Q=false}});if(Q){D={};A={parent:this};N=false;H=G.find("input");for(M=0,P=H.length;M<P;M++){I=H[M];if((I.value!=null)&&jQuery.trim(I.value).length>0){D[I.name]=I.value}if(I.type==="file"){N=true}}E=G.find("textarea");for(L=0,F=E.length;L<F;L++){I=E[L];if((I.value!=null)&&jQuery.trim(I.value).length>0){D[I.name]=I.value}}B=G.find("select");for(K=0,C=B.length;K<C;K++){I=B[K];J=this.getSelectedValue(I);if((J!=null)&&jQuery.trim(J).length>0){D[I.name]=J}}A.responseContentType=$("div select[name=responseContentType]",$(this.el)).val();A.requestContentType=$("div select[name=parameterContentType]",$(this.el)).val();$(".response_throbber",$(this.el)).show();if(N){return this.handleFileUpload(D,G)}else{return this.model["do"](D,A,this.showCompleteStatus,this.showErrorStatus,this)}}};y.prototype.success=function(A,B){return B.showCompleteStatus(A)};y.prototype.handleFileUpload=function(R,I){var M,H,C,N,L,K,P,J,G,F,D,Q,U,T,S,E,B,A,V,O=this;E=I.serializeArray();for(J=0,Q=E.length;J<Q;J++){N=E[J];if((N.value!=null)&&jQuery.trim(N.value).length>0){R[N.name]=N.value}}M=new FormData();P=0;B=this.model.parameters;for(G=0,U=B.length;G<U;G++){K=B[G];if(K.paramType==="form"){if(K.type.toLowerCase()!=="file"&&R[K.name]!==void 0){M.append(K.name,R[K.name])}}}C={};A=this.model.parameters;for(F=0,T=A.length;F<T;F++){K=A[F];if(K.paramType==="header"){C[K.name]=R[K.name]}}V=I.find('input[type~="file"]');for(D=0,S=V.length;D<S;D++){H=V[D];if(typeof H.files[0]!=="undefined"){M.append($(H).attr("name"),H.files[0]);P+=1}}this.invocationUrl=this.model.supportHeaderParams()?(C=this.model.getHeaderParams(R),this.model.urlify(R,false)):this.model.urlify(R,true);$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(this.invocationUrl);L={type:this.model.method,url:this.invocationUrl,headers:C,data:M,dataType:"json",contentType:false,processData:false,error:function(X,Y,W){return O.showErrorStatus(O.wrap(X),O)},success:function(W){return O.showResponse(W,O)},complete:function(W){return O.showCompleteStatus(O.wrap(W),O)}};if(window.authorizations){window.authorizations.apply(L)}if(P===0){L.data.append("fake","true")}jQuery.ajax(L);return false};y.prototype.wrap=function(E){var C,F,H,B,G,D,A;H={};F=E.getAllResponseHeaders().split("\r");for(D=0,A=F.length;D<A;D++){B=F[D];C=B.split(":");if(C[0]!==void 0&&C[1]!==void 0){H[C[0].trim()]=C[1].trim()}}G={};G.content={};G.content.data=E.responseText;G.headers=H;G.request={};G.request.url=this.invocationUrl;G.status=E.status;return G};y.prototype.getSelectedValue=function(A){var D,C,F,B,E;if(!A.multiple){return A.value}else{C=[];E=A.options;for(F=0,B=E.length;F<B;F++){D=E[F];if(D.selected){C.push(D.value)}}if(C.length>0){return C}else{return null}}};y.prototype.hideResponse=function(A){if(A!=null){A.preventDefault()}$(".response",$(this.el)).slideUp();return $(".response_hider",$(this.el)).fadeOut()};y.prototype.showResponse=function(A){var B;B=JSON.stringify(A,null,"\t").replace(/\n/g,"<br>");return $(".response_body",$(this.el)).html(escape(B))};y.prototype.showErrorStatus=function(B,A){return A.showStatus(B)};y.prototype.showCompleteStatus=function(B,A){return A.showStatus(B)};y.prototype.formatXml=function(H){var D,G,B,I,N,J,C,A,L,M,F,E,K;A=/(>)(<)(\/*)/g;M=/[ ]*(.*)[ ]+\n/g;D=/(<.+>)(.+\n)/g;H=H.replace(A,"$1\n$2$3").replace(M,"$1\n").replace(D,"$1\n$2");C=0;G="";N=H.split("\n");B=0;I="other";L={"single->single":0,"single->closing":-1,"single->opening":0,"single->other":0,"closing->single":0,"closing->closing":-1,"closing->opening":0,"closing->other":0,"opening->single":1,"opening->closing":0,"opening->opening":1,"opening->other":1,"other->single":0,"other->closing":-1,"other->opening":0,"other->other":0};F=function(T){var P,O,R,V,S,Q,U;Q={single:Boolean(T.match(/<.+\/>/)),closing:Boolean(T.match(/<\/.+>/)),opening:Boolean(T.match(/<[^!?].*>/))};S=((function(){var W;W=[];for(R in Q){U=Q[R];if(U){W.push(R)}}return W})())[0];S=S===void 0?"other":S;P=I+"->"+S;I=S;V="";B+=L[P];V=((function(){var X,Y,W;W=[];for(O=X=0,Y=B;0<=Y?X<Y:X>Y;O=0<=Y?++X:--X){W.push(" ")}return W})()).join("");if(P==="opening->closing"){return G=G.substr(0,G.length-1)+T+"\n"}else{return G+=V+T+"\n"}};for(E=0,K=N.length;E<K;E++){J=N[E];F(J)}return G};y.prototype.showStatus=function(F){var C,J,L,I,D,M,A,E,H,G,B;if(F.content===void 0){J=F.data;B=F.url}else{J=F.content.data;B=F.request.url}D=F.headers;L=D&&D["Content-Type"]?D["Content-Type"].split(";")[0].trim():null;if(!J){C=$("<code />").text("no content");E=$('<pre class="json" />').append(C)}else{if(L==="application/json"||/\+json$/.test(L)){M=null;try{M=JSON.stringify(JSON.parse(J),null," ")}catch(K){I=K;M="can't parse JSON. Raw result:\n\n"+J}C=$("<code />").text(M);E=$('<pre class="json" />').append(C)}else{if(L==="application/xml"||/\+xml$/.test(L)){C=$("<code />").text(this.formatXml(J));E=$('<pre class="xml" />').append(C)}else{if(L==="text/html"){C=$("<code />").html(_.escape(J));E=$('<pre class="xml" />').append(C)}else{if(/^image\//.test(L)){E=$("<img>").attr("src",B)}else{C=$("<code />").text(J);E=$('<pre class="json" />').append(C)}}}}}H=E;$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(B);$(".response_code",$(this.el)).html("<pre>"+F.status+"</pre>");$(".response_body",$(this.el)).html(H);$(".response_headers",$(this.el)).html("<pre>"+_.escape(JSON.stringify(F.headers,null," ")).replace(/\n/g,"<br>")+"</pre>");$(".response",$(this.el)).slideDown();$(".response_hider",$(this.el)).show();$(".response_throbber",$(this.el)).hide();G=$(".response_body",$(this.el))[0];A=this.options.swaggerOptions;if(A.highlightSizeThreshold&&F.data.length>A.highlightSizeThreshold){return G}else{return hljs.highlightBlock(G)}};y.prototype.toggleOperationContent=function(){var A;A=$("#"+Docs.escapeResourceName(this.model.parentId)+"_"+this.model.nickname+"_content");if(A.is(":visible")){return Docs.collapseOperation(A)}else{return Docs.expandOperation(A)}};return y})(Backbone.View);p=(function(z){v(y,z);function y(){d=y.__super__.constructor.apply(this,arguments);return d}y.prototype.initialize=function(){};y.prototype.render=function(){var B,A,C;C=this.template();$(this.el).html(C(this.model));if(swaggerUi.api.models.hasOwnProperty(this.model.responseModel)){B={sampleJSON:JSON.stringify(swaggerUi.api.models[this.model.responseModel].createJSONSample(),null,2),isParam:false,signature:swaggerUi.api.models[this.model.responseModel].getMockSignature()};A=new i({model:B,tagName:"div"});$(".model-signature",this.$el).append(A.render().el)}else{$(".model-signature",this.$el).html("")}return this};y.prototype.template=function(){return Handlebars.templates.status_code};return y})(Backbone.View);k=(function(z){v(y,z);function y(){b=y.__super__.constructor.apply(this,arguments);return b}y.prototype.initialize=function(){return Handlebars.registerHelper("isArray",function(B,A){if(B.type.toLowerCase()==="array"||B.allowMultiple){return A.fn(this)}else{return A.inverse(this)}})};y.prototype.render=function(){var A,B,E,C,F,D,I,J,H,G;G=this.model.type||this.model.dataType;if(typeof G==="undefined"){D=this.model.schema;if(D&&D["$ref"]){C=D["$ref"];if(C.indexOf("#/definitions/")===0){G=C.substring("#/definitions/".length)}else{G=C}}}this.model.type=G;this.model.paramType=this.model["in"]||this.model.paramType;if(this.model.paramType==="body"){this.model.isBody=true}if(G&&G.toLowerCase()==="file"){this.model.isFile=true}this.model["default"]=this.model["default"]||this.model.defaultValue;H=this.template();$(this.el).html(H(this.model));I={sampleJSON:this.model.sampleJSON,isParam:true,signature:this.model.signature};if(this.model.sampleJSON){J=new i({model:I,tagName:"div"});$(".model-signature",$(this.el)).append(J.render().el)}else{$(".model-signature",$(this.el)).html(this.model.signature)}B=false;if(this.model.isBody){B=true}A={isParam:B};A.consumes=this.model.consumes;if(B){E=new l({model:A});$(".parameter-content-type",$(this.el)).append(E.render().el)}else{F=new m({model:A});$(".response-content-type",$(this.el)).append(F.render().el)}return this};y.prototype.template=function(){if(this.model.isList){return Handlebars.templates.param_list}else{if(this.options.readOnly){if(this.model.required){return Handlebars.templates.param_readonly_required}else{return Handlebars.templates.param_readonly}}else{if(this.model.required){return Handlebars.templates.param_required}else{return Handlebars.templates.param}}}};return y})(Backbone.View);i=(function(z){v(y,z);function y(){a=y.__super__.constructor.apply(this,arguments);return a}y.prototype.events={"click a.description-link":"switchToDescription","click a.snippet-link":"switchToSnippet","mousedown .snippet":"snippetToTextArea"};y.prototype.initialize=function(){};y.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));this.switchToSnippet();this.isParam=this.model.isParam;if(this.isParam){$(".notice",$(this.el)).text("Click to set as parameter value")}return this};y.prototype.template=function(){return Handlebars.templates.signature};y.prototype.switchToDescription=function(A){if(A!=null){A.preventDefault()}$(".snippet",$(this.el)).hide();$(".description",$(this.el)).show();$(".description-link",$(this.el)).addClass("selected");return $(".snippet-link",$(this.el)).removeClass("selected")};y.prototype.switchToSnippet=function(A){if(A!=null){A.preventDefault()}$(".description",$(this.el)).hide();$(".snippet",$(this.el)).show();$(".snippet-link",$(this.el)).addClass("selected");return $(".description-link",$(this.el)).removeClass("selected")};y.prototype.snippetToTextArea=function(A){var B;if(this.isParam){if(A!=null){A.preventDefault()}B=$("textarea",$(this.el.parentNode.parentNode.parentNode));if($.trim(B.val())===""){return B.val(this.model.sampleJSON)}}};return y})(Backbone.View);j=(function(y){v(z,y);function z(){x=z.__super__.constructor.apply(this,arguments);return x}z.prototype.initialize=function(){};z.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=contentType]",$(this.el)).text("Response Content Type");return this};z.prototype.template=function(){return Handlebars.templates.content_type};return z})(Backbone.View);m=(function(y){v(z,y);function z(){w=z.__super__.constructor.apply(this,arguments);return w}z.prototype.initialize=function(){};z.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=responseContentType]",$(this.el)).text("Response Content Type");return this};z.prototype.template=function(){return Handlebars.templates.response_content_type};return z})(Backbone.View);l=(function(z){v(y,z);function y(){c=y.__super__.constructor.apply(this,arguments);return c}y.prototype.initialize=function(){};y.prototype.render=function(){var A;A=this.template();$(this.el).html(A(this.model));$("label[for=parameterContentType]",$(this.el)).text("Parameter content type:");return this};y.prototype.template=function(){return Handlebars.templates.parameter_content_type};return y})(Backbone.View)}).call(this);
$(function(){$.fn.vAlign=function(){return this.each(function(c){var a=$(this).height();var d=$(this).parent().height();var b=(d-a)/2;$(this).css("margin-top",b)})};$.fn.stretchFormtasticInputWidthToParent=function(){return this.each(function(b){var d=$(this).closest("form").innerWidth();var c=parseInt($(this).closest("form").css("padding-left"),10)+parseInt($(this).closest("form").css("padding-right"),10);var a=parseInt($(this).css("padding-left"),10)+parseInt($(this).css("padding-right"),10);$(this).css("width",d-c-a)})};$("form.formtastic li.string input, form.formtastic textarea").stretchFormtasticInputWidthToParent();$("ul.downplayed li div.content p").vAlign();$("form.sandbox").submit(function(){var a=true;$(this).find("input.required").each(function(){$(this).removeClass("error");if($(this).val()==""){$(this).addClass("error");$(this).wiggle();a=false}});return a})});function clippyCopiedCallback(b){$("#api_key_copied").fadeIn().delay(1000).fadeOut()}log=function(){log.history=log.history||[];log.history.push(arguments);if(this.console){console.log(Array.prototype.slice.call(arguments)[0])}};if(Function.prototype.bind&&console&&typeof console.log=="object"){["log","info","warn","error","assert","dir","clear","profile","profileEnd"].forEach(function(a){console[a]=this.bind(console[a],console)},Function.prototype.call)}var Docs={shebang:function(){var b=$.param.fragment().split("/");b.shift();switch(b.length){case 1:var d="resource_"+b[0];Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});break;case 2:Docs.expandEndpointListForResource(b[0]);$("#"+d).slideto({highlight:false});var c=b.join("_");var a=c+"_content";Docs.expandOperation($("#"+a));$("#"+c).slideto({highlight:false});break}},toggleEndpointListForResource:function(b){var a=$("li#resource_"+Docs.escapeResourceName(b)+" ul.endpoints");if(a.is(":visible")){Docs.collapseEndpointListForResource(b)}else{Docs.expandEndpointListForResource(b)}},expandEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);if(b==""){$(".resource ul.endpoints").slideDown();return}$("li#resource_"+b).addClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideDown()},collapseEndpointListForResource:function(b){var b=Docs.escapeResourceName(b);$("li#resource_"+b).removeClass("active");var a=$("li#resource_"+b+" ul.endpoints");a.slideUp()},expandOperationsForResource:function(a){Docs.expandEndpointListForResource(a);if(a==""){$(".resource ul.endpoints li.operation div.content").slideDown();return}$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.expandOperation($(this))})},collapseOperationsForResource:function(a){Docs.expandEndpointListForResource(a);$("li#resource_"+Docs.escapeResourceName(a)+" li.operation div.content").each(function(){Docs.collapseOperation($(this))})},escapeResourceName:function(a){return a.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]\^`{|}~]/g,"\\$&")},expandOperation:function(a){a.slideDown()},collapseOperation:function(a){a.slideUp()}};(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.apikey_button_view=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+="<div class='auth_button' id='apikey_button'><img class='auth_icon' alt='apply api key' src='images/apikey.jpeg'></div>\n<div class='auth_container' id='apikey_container'>\n <div class='key_input_container'>\n <div class='auth_label'>";if(c=d.keyName){c=c.call(k,{hash:{},data:i})}else{c=k.keyName;c=typeof c===f?c.apply(k):c}g+=h(c)+'</div>\n <input placeholder="api_key" class="auth_input" id="input_apiKey_entry" name="apiKey" type="text"/>\n <div class=\'auth_submit\'><a class=\'auth_submit_button\' id="apply_api_key" href="#">apply</a></div>\n </div>\n</div>\n\n';return g})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.basic_auth_button_view=b(function(f,g,d,c,e){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,f.helpers);e=e||{};return'<div class=\'auth_button\' id=\'basic_auth_button\'><img class=\'auth_icon\' src=\'images/password.jpeg\'></div>\n<div class=\'auth_container\' id=\'basic_auth_container\'>\n <div class=\'key_input_container\'>\n <div class="auth_label">Username</div>\n <input placeholder="username" class="auth_input" id="input_username" name="username" type="text"/>\n <div class="auth_label">Password</div>\n <input placeholder="password" class="auth_input" id="input_password" name="password" type="password"/>\n <div class=\'auth_submit\'><a class=\'auth_submit_button\' id="apply_basic_auth" href="#">apply</a></div>\n </div>\n</div>\n\n'})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="contentType"></label>\n<select name="contentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.main=b(function(h,n,g,m,l){this.compilerInfo=[4,">= 1.0.0"];g=this.merge(g,h.helpers);l=l||{};var j="",c,s,i="function",k=this.escapeExpression,q=this;function f(x,w){var t="",v,u;t+='\n <div class="info_title">'+k(((v=((v=x.info),v==null||v===false?v:v.title)),typeof v===i?v.apply(x):v))+'</div>\n <div class="info_description">';u=((v=((v=x.info),v==null||v===false?v:v.description)),typeof v===i?v.apply(x):v);if(u||u===0){t+=u}t+="</div>\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.termsOfServiceUrl),{hash:{},inverse:q.noop,fn:q.program(2,d,w),data:w});if(u||u===0){t+=u}t+="\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.contact),{hash:{},inverse:q.noop,fn:q.program(4,r,w),data:w});if(u||u===0){t+=u}t+="\n ";u=g["if"].call(x,((v=x.info),v==null||v===false?v:v.license),{hash:{},inverse:q.noop,fn:q.program(6,p,w),data:w});if(u||u===0){t+=u}t+="\n ";return t}function d(w,v){var t="",u;t+='<div class="info_tos"><a href="'+k(((u=((u=w.info),u==null||u===false?u:u.termsOfServiceUrl)),typeof u===i?u.apply(w):u))+'">Terms of service</a></div>';return t}function r(w,v){var t="",u;t+="<div class='info_contact'><a href=\"mailto:"+k(((u=((u=((u=w.info),u==null||u===false?u:u.contact)),u==null||u===false?u:u.name)),typeof u===i?u.apply(w):u))+'">Contact the developer</a></div>';return t}function p(w,v){var t="",u;t+="<div class='info_license'><a href='"+k(((u=((u=((u=w.info),u==null||u===false?u:u.license)),u==null||u===false?u:u.url)),typeof u===i?u.apply(w):u))+"'>"+k(((u=((u=((u=w.info),u==null||u===false?u:u.license)),u==null||u===false?u:u.name)),typeof u===i?u.apply(w):u))+"</a></div>";return t}function o(w,v){var t="",u;t+='\n , <span style="font-variant: small-caps">api version</span>: '+k(((u=((u=w.info),u==null||u===false?u:u.version)),typeof u===i?u.apply(w):u))+"\n ";return t}function e(w,v){var t="",u;t+='\n <span style="float:right"><a href="';if(u=g.validatorUrl){u=u.call(w,{hash:{},data:v})}else{u=w.validatorUrl;u=typeof u===i?u.apply(w):u}t+=k(u)+"/debug?url=";if(u=g.url){u=u.call(w,{hash:{},data:v})}else{u=w.url;u=typeof u===i?u.apply(w):u}t+=k(u)+'"><img id="validator" src="';if(u=g.validatorUrl){u=u.call(w,{hash:{},data:v})}else{u=w.validatorUrl;u=typeof u===i?u.apply(w):u}t+=k(u)+"?url=";if(u=g.url){u=u.call(w,{hash:{},data:v})}else{u=w.url;u=typeof u===i?u.apply(w):u}t+=k(u)+'"></a>\n </span>\n ';return t}j+="<div class='info' id='api_info'>\n ";c=g["if"].call(n,n.info,{hash:{},inverse:q.noop,fn:q.program(1,f,l),data:l});if(c||c===0){j+=c}j+="\n</div>\n<div class='container' id='resources_container'>\n <ul id='resources'></ul>\n\n <div class=\"footer\">\n <br>\n <br>\n <h4 style=\"color: #999\">[ <span style=\"font-variant: small-caps\">base url</span>: ";if(c=g.basePath){c=c.call(n,{hash:{},data:l})}else{c=n.basePath;c=typeof c===i?c.apply(n):c}j+=k(c)+"\n ";s=g["if"].call(n,((c=n.info),c==null||c===false?c:c.version),{hash:{},inverse:q.noop,fn:q.program(8,o,l),data:l});if(s||s===0){j+=s}j+="]\n ";s=g["if"].call(n,n.validatorUrl,{hash:{},inverse:q.noop,fn:q.program(10,e,l),data:l});if(s||s===0){j+=s}j+="\n </h4>\n </div>\n</div>\n";return j})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.operation=b(function(j,u,s,o,A){this.compilerInfo=[4,">= 1.0.0"];s=this.merge(s,j.helpers);A=A||{};var t="",k,f,e="function",d=this.escapeExpression,r=this,c=s.blockHelperMissing;function q(C,B){return"deprecated"}function p(C,B){return"\n <h4>Warning: Deprecated</h4>\n "}function n(E,D){var B="",C;B+="\n <h4>Implementation Notes</h4>\n <p>";if(C=s.description){C=C.call(E,{hash:{},data:D})}else{C=E.description;C=typeof C===e?C.apply(E):C}if(C||C===0){B+=C}B+="</p>\n ";return B}function m(C,B){return'\n <div class="auth">\n <span class="api-ic ic-error"></span>'}function i(E,D){var B="",C;B+='\n <div id="api_information_panel" style="top: 526px; left: 776px; display: none;">\n ';C=s.each.call(E,E,{hash:{},inverse:r.noop,fn:r.program(10,z,D),data:D});if(C||C===0){B+=C}B+="\n </div>\n ";return B}function z(F,E){var B="",D,C;B+="\n <div title='";C=((D=F.description),typeof D===e?D.apply(F):D);if(C||C===0){B+=C}B+="'>"+d(((D=F.scope),typeof D===e?D.apply(F):D))+"</div>\n ";return B}function y(C,B){return"</div>"}function x(C,B){return'\n <div class=\'access\'>\n <span class="api-ic ic-off" title="click to authenticate"></span>\n </div>\n '}function w(C,B){return'\n <h4>Response Class</h4>\n <p><span class="model-signature" /></p>\n <br/>\n <div class="response-content-type" />\n '}function v(C,B){return'\n <h4>Parameters</h4>\n <table class=\'fullwidth\'>\n <thead>\n <tr>\n <th style="width: 100px; max-width: 100px">Parameter</th>\n <th style="width: 310px; max-width: 310px">Value</th>\n <th style="width: 200px; max-width: 200px">Description</th>\n <th style="width: 100px; max-width: 100px">Parameter Type</th>\n <th style="width: 220px; max-width: 230px">Data Type</th>\n </tr>\n </thead>\n <tbody class="operation-params">\n\n </tbody>\n </table>\n '}function l(C,B){return"\n <div style='margin:0;padding:0;display:inline'></div>\n <h4>Response Messages</h4>\n <table class='fullwidth'>\n <thead>\n <tr>\n <th>HTTP Status Code</th>\n <th>Reason</th>\n <th>Response Model</th>\n </tr>\n </thead>\n <tbody class=\"operation-status\">\n \n </tbody>\n </table>\n "}function h(C,B){return"\n "}function g(C,B){return"\n <div class='sandbox_header'>\n <input class='submit' name='commit' type='button' value='Try it out!' />\n <a href='#' class='response_hider' style='display:none'>Hide Response</a>\n <span class='response_throbber' style='display:none'></span>\n </div>\n "}t+="\n <ul class='operations' >\n <li class='";if(k=s.method){k=k.call(u,{hash:{},data:A})}else{k=u.method;k=typeof k===e?k.apply(u):k}t+=d(k)+" operation' id='";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"_";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"'>\n <div class='heading'>\n <h3>\n <span class='http_method'>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+'\' class="toggleOperation">';if(k=s.method){k=k.call(u,{hash:{},data:A})}else{k=u.method;k=typeof k===e?k.apply(u):k}t+=d(k)+"</a>\n </span>\n <span class='path'>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"' class=\"toggleOperation ";k=s["if"].call(u,u.deprecated,{hash:{},inverse:r.noop,fn:r.program(1,q,A),data:A});if(k||k===0){t+=k}t+='">';if(k=s.path){k=k.call(u,{hash:{},data:A})}else{k=u.path;k=typeof k===e?k.apply(u):k}t+=d(k)+"</a>\n </span>\n </h3>\n <ul class='options'>\n <li>\n <a href='#!/";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"/";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+'\' class="toggleOperation">';if(k=s.summary){k=k.call(u,{hash:{},data:A})}else{k=u.summary;k=typeof k===e?k.apply(u):k}if(k||k===0){t+=k}t+="</a>\n </li>\n </ul>\n </div>\n <div class='content' id='";if(k=s.parentId){k=k.call(u,{hash:{},data:A})}else{k=u.parentId;k=typeof k===e?k.apply(u):k}t+=d(k)+"_";if(k=s.nickname){k=k.call(u,{hash:{},data:A})}else{k=u.nickname;k=typeof k===e?k.apply(u):k}t+=d(k)+"_content' style='display:none'>\n ";k=s["if"].call(u,u.deprecated,{hash:{},inverse:r.noop,fn:r.program(3,p,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.description,{hash:{},inverse:r.noop,fn:r.program(5,n,A),data:A});if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(7,m,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";k=s.each.call(u,u.oauth,{hash:{},inverse:r.noop,fn:r.program(9,i,A),data:A});if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(12,y,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";f={hash:{},inverse:r.noop,fn:r.program(14,x,A),data:A};if(k=s.oauth){k=k.call(u,f)}else{k=u.oauth;k=typeof k===e?k.apply(u):k}if(!s.oauth){k=c.call(u,k,f)}if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.type,{hash:{},inverse:r.noop,fn:r.program(16,w,A),data:A});if(k||k===0){t+=k}t+="\n <form accept-charset='UTF-8' class='sandbox'>\n <div style='margin:0;padding:0;display:inline'></div>\n ";k=s["if"].call(u,u.parameters,{hash:{},inverse:r.noop,fn:r.program(18,v,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.responseMessages,{hash:{},inverse:r.noop,fn:r.program(20,l,A),data:A});if(k||k===0){t+=k}t+="\n ";k=s["if"].call(u,u.isReadOnly,{hash:{},inverse:r.program(24,g,A),fn:r.program(22,h,A),data:A});if(k||k===0){t+=k}t+="\n </form>\n <div class='response' style='display:none'>\n <h4>Request URL</h4>\n <div class='block request_url'></div>\n <h4>Response Body</h4>\n <div class='block response_body'></div>\n <h4>Response Code</h4>\n <div class='block response_code'></div>\n <h4>Response Headers</h4>\n <div class='block response_headers'></div>\n </div>\n </div>\n </li>\n </ul>\n";return t})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param=b(function(f,q,o,j,t){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);t=t||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(4,k,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function l(y,x){var v="",w;v+='\n <input type="file" name=\'';if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'/>\n <div class="parameter-content-type" />\n ';return v}function k(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y["default"],{hash:{},inverse:n.program(7,h,x),fn:n.program(5,i,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function i(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"'>";if(w=o["default"]){w=w.call(y,{hash:{},data:x})}else{w=y["default"];w=typeof w===d?w.apply(y):w}v+=c(w)+"</textarea>\n ";return v}function h(y,x){var v="",w;v+="\n <textarea class='body-textarea' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return v}function e(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y.isFile,{hash:{},inverse:n.program(10,u,x),fn:n.program(2,l,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function u(y,x){var v="",w;v+="\n ";w=o["if"].call(y,y["default"],{hash:{},inverse:n.program(13,r,x),fn:n.program(11,s,x),data:x});if(w||w===0){v+=w}v+="\n ";return v}function s(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value='";if(w=o["default"]){w=w.call(y,{hash:{},data:x})}else{w=y["default"];w=typeof w===d?w.apply(y):w}v+=c(w)+"'/>\n ";return v}function r(y,x){var v="",w;v+="\n <input class='parameter' minlength='0' name='";if(w=o.name){w=w.call(y,{hash:{},data:x})}else{w=y.name;w=typeof w===d?w.apply(y):w}v+=c(w)+"' placeholder='' type='text' value=''/>\n ";return v}p+="<td class='code'>";if(g=o.name){g=g.call(q,{hash:{},data:t})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,t),fn:n.program(1,m,t),data:t});if(g||g===0){p+=g}p+="\n\n</td>\n<td>";if(g=o.description){g=g.call(q,{hash:{},data:t})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:t})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td>\n <span class="model-signature"></span>\n</td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_list=b(function(h,t,r,m,y){this.compilerInfo=[4,">= 1.0.0"];r=this.merge(r,h.helpers);y=y||{};var s="",j,g,e,p=this,q=r.helperMissing,d="function",c=this.escapeExpression;function o(A,z){return" multiple='multiple'"}function n(A,z){return"\n "}function l(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C["default"],{hash:{},inverse:p.program(8,i,B),fn:p.program(6,k,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function k(A,z){return"\n "}function i(E,D){var z="",C,B,A;z+="\n ";A={hash:{},inverse:p.program(11,x,D),fn:p.program(9,f,D),data:D};B=((C=r.isArray||E.isArray),C?C.call(E,E,A):q.call(E,"isArray",E,A));if(B||B===0){z+=B}z+="\n ";return z}function f(A,z){return"\n "}function x(A,z){return"\n <option selected=\"\" value=''></option>\n "}function w(C,B){var z="",A;z+="\n ";A=r["if"].call(C,C.isDefault,{hash:{},inverse:p.program(16,u,B),fn:p.program(14,v,B),data:B});if(A||A===0){z+=A}z+="\n ";return z}function v(C,B){var z="",A;z+='\n <option selected="" value=\'';if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+" (default)</option>\n ";return z}function u(C,B){var z="",A;z+="\n <option value='";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"'>";if(A=r.value){A=A.call(C,{hash:{},data:B})}else{A=C.value;A=typeof A===d?A.apply(C):A}z+=c(A)+"</option>\n ";return z}s+="<td class='code'>";if(j=r.name){j=j.call(t,{hash:{},data:y})}else{j=t.name;j=typeof j===d?j.apply(t):j}s+=c(j)+"</td>\n<td>\n <select ";e={hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y};g=((j=r.isArray||t.isArray),j?j.call(t,t,e):q.call(t,"isArray",t,e));if(g||g===0){s+=g}s+=" class='parameter' name='";if(g=r.name){g=g.call(t,{hash:{},data:y})}else{g=t.name;g=typeof g===d?g.apply(t):g}s+=c(g)+"'>\n ";g=r["if"].call(t,t.required,{hash:{},inverse:p.program(5,l,y),fn:p.program(3,n,y),data:y});if(g||g===0){s+=g}s+="\n ";g=r.each.call(t,((j=t.allowableValues),j==null||j===false?j:j.descriptiveValues),{hash:{},inverse:p.noop,fn:p.program(13,w,y),data:y});if(g||g===0){s+=g}s+="\n </select>\n</td>\n<td>";if(g=r.description){g=g.call(t,{hash:{},data:y})}else{g=t.description;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+="</td>\n<td>";if(g=r.paramType){g=g.call(t,{hash:{},data:y})}else{g=t.paramType;g=typeof g===d?g.apply(t):g}if(g||g===0){s+=g}s+='</td>\n<td><span class="model-signature"></span></td>';return s})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f["default"]){r=r.call(t,{hash:{},data:s})}else{r=t["default"];r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t["default"],{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f["default"]){r=r.call(t,{hash:{},data:s})}else{r=t["default"];r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_readonly_required=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var q="",r;q+="\n <textarea class='body-textarea' readonly='readonly' placeholder='(required)' name='";if(r=f.name){r=r.call(t,{hash:{},data:s})}else{r=t.name;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>";if(r=f["default"]){r=r.call(t,{hash:{},data:s})}else{r=t["default"];r=typeof r===h?r.apply(t):r}q+=j(r)+"</textarea>\n ";return q}function c(t,s){var q="",r;q+="\n ";r=f["if"].call(t,t["default"],{hash:{},inverse:o.program(6,n,s),fn:o.program(4,p,s),data:s});if(r||r===0){q+=r}q+="\n ";return q}function p(t,s){var q="",r;q+="\n ";if(r=f["default"]){r=r.call(t,{hash:{},data:s})}else{r=t["default"];r=typeof r===h?r.apply(t):r}q+=j(r)+"\n ";return q}function n(r,q){return"\n (empty)\n "}i+="<td class='code required'>";if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</td>\n<td>\n ";d=f["if"].call(m,m.isBody,{hash:{},inverse:o.program(3,c,k),fn:o.program(1,e,k),data:k});if(d||d===0){i+=d}i+="\n</td>\n<td>";if(d=f.description){d=d.call(m,{hash:{},data:k})}else{d=m.description;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="</td>\n<td>";if(d=f.paramType){d=d.call(m,{hash:{},data:k})}else{d=m.paramType;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+='</td>\n<td><span class="model-signature"></span></td>\n';return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.param_required=b(function(f,q,o,j,u){this.compilerInfo=[4,">= 1.0.0"];o=this.merge(o,f.helpers);u=u||{};var p="",g,d="function",c=this.escapeExpression,n=this;function m(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(4,k,y),fn:n.program(2,l,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function l(z,y){var w="",x;w+='\n <input type="file" name=\'';if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function k(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z["default"],{hash:{},inverse:n.program(7,h,y),fn:n.program(5,i,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function i(z,y){var w="",x;w+="\n <textarea class='body-textarea required' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'>";if(x=o["default"]){x=x.call(z,{hash:{},data:y})}else{x=z["default"];x=typeof x===d?x.apply(z):x}w+=c(x)+"</textarea>\n ";return w}function h(z,y){var w="",x;w+="\n <textarea class='body-textarea required' placeholder='(required)' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+'\'></textarea>\n <br />\n <div class="parameter-content-type" />\n ';return w}function e(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z.isFile,{hash:{},inverse:n.program(12,t,y),fn:n.program(10,v,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function v(z,y){var w="",x;w+="\n <input class='parameter' class='required' type='file' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function t(z,y){var w="",x;w+="\n ";x=o["if"].call(z,z["default"],{hash:{},inverse:n.program(15,r,y),fn:n.program(13,s,y),data:y});if(x||x===0){w+=x}w+="\n ";return w}function s(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value='";if(x=o["default"]){x=x.call(z,{hash:{},data:y})}else{x=z["default"];x=typeof x===d?x.apply(z):x}w+=c(x)+"'/>\n ";return w}function r(z,y){var w="",x;w+="\n <input class='parameter required' minlength='1' name='";if(x=o.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===d?x.apply(z):x}w+=c(x)+"' placeholder='(required)' type='text' value=''/>\n ";return w}p+="<td class='code required'>";if(g=o.name){g=g.call(q,{hash:{},data:u})}else{g=q.name;g=typeof g===d?g.apply(q):g}p+=c(g)+"</td>\n<td>\n ";g=o["if"].call(q,q.isBody,{hash:{},inverse:n.program(9,e,u),fn:n.program(1,m,u),data:u});if(g||g===0){p+=g}p+="\n</td>\n<td>\n <strong>";if(g=o.description){g=g.call(q,{hash:{},data:u})}else{g=q.description;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+="</strong>\n</td>\n<td>";if(g=o.paramType){g=g.call(q,{hash:{},data:u})}else{g=q.paramType;g=typeof g===d?g.apply(q):g}if(g||g===0){p+=g}p+='</td>\n<td><span class="model-signature"></span></td>\n';return p})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.parameter_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.consumes,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="parameterContentType"></label>\n<select name="parameterContentType">\n';c=f["if"].call(l,l.consumes,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.resource=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,p,h="function",j=this.escapeExpression,o=this,n=f.blockHelperMissing;function e(r,q){return" : "}function c(t,s){var q="",r;q+="<li>\n <a href='";if(r=f.url){r=r.call(t,{hash:{},data:s})}else{r=t.url;r=typeof r===h?r.apply(t):r}q+=j(r)+"'>Raw</a>\n </li>";return q}i+="<div class='heading'>\n <h2>\n <a href='#!/";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'\' class="toggleEndpointList" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">';if(d=f.name){d=d.call(m,{hash:{},data:k})}else{d=m.name;d=typeof d===h?d.apply(m):d}i+=j(d)+"</a> ";p={hash:{},inverse:o.noop,fn:o.program(1,e,k),data:k};if(d=f.summary){d=d.call(m,p)}else{d=m.summary;d=typeof d===h?d.apply(m):d}if(!f.summary){d=n.call(m,d,p)}if(d||d===0){i+=d}if(d=f.summary){d=d.call(m,{hash:{},data:k})}else{d=m.summary;d=typeof d===h?d.apply(m):d}if(d||d===0){i+=d}i+="\n </h2>\n <ul class='options'>\n <li>\n <a href='#!/";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+"' id='endpointListTogger_";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'\' class="toggleEndpointList" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">Show/Hide</a>\n </li>\n <li>\n <a href=\'#\' class="collapseResource" data-id="';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+'">\n List Operations\n </a>\n </li>\n <li>\n <a href=\'#\' class="expandResource" data-id=';if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+">\n Expand Operations\n </a>\n </li>\n ";p={hash:{},inverse:o.noop,fn:o.program(3,c,k),data:k};if(d=f.url){d=d.call(m,p)}else{d=m.url;d=typeof d===h?d.apply(m):d}if(!f.url){d=n.call(m,d,p)}if(d||d===0){i+=d}i+="\n </ul>\n</div>\n<ul class='endpoints' id='";if(d=f.id){d=d.call(m,{hash:{},data:k})}else{d=m.id;d=typeof d===h?d.apply(m):d}i+=j(d)+"_endpoint_list' style='display:none'>\n\n</ul>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.response_content_type=b(function(g,l,f,k,j){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);j=j||{};var i="",c,h="function",m=this;function e(r,q){var o="",p;o+="\n ";p=f.each.call(r,r.produces,{hash:{},inverse:m.noop,fn:m.program(2,d,q),data:q});if(p||p===0){o+=p}o+="\n";return o}function d(r,q){var o="",p;o+='\n <option value="';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+='">';p=(typeof r===h?r.apply(r):r);if(p||p===0){o+=p}o+="</option>\n ";return o}function n(p,o){return'\n <option value="application/json">application/json</option>\n'}i+='<label for="responseContentType"></label>\n<select name="responseContentType">\n';c=f["if"].call(l,l.produces,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j),data:j});if(c||c===0){i+=c}i+="\n</select>\n";return i})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.signature=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+='<div>\n<ul class="signature-nav">\n <li><a class="description-link" href="#">Model</a></li>\n <li><a class="snippet-link" href="#">Model Schema</a></li>\n</ul>\n<div>\n\n<div class="signature-container">\n <div class="description">\n ';if(c=d.signature){c=c.call(k,{hash:{},data:i})}else{c=k.signature;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+='\n </div>\n\n <div class="snippet">\n <pre><code>';if(c=d.sampleJSON){c=c.call(k,{hash:{},data:i})}else{c=k.sampleJSON;c=typeof c===f?c.apply(k):c}g+=h(c)+'</code></pre>\n <small class="notice"></small>\n </div>\n</div>\n\n';return g})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.status_code=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+="<td width='15%' class='code'>";if(c=d.code){c=c.call(k,{hash:{},data:i})}else{c=k.code;c=typeof c===f?c.apply(k):c}g+=h(c)+"</td>\n<td>";if(c=d.message){c=c.call(k,{hash:{},data:i})}else{c=k.message;c=typeof c===f?c.apply(k):c}if(c||c===0){g+=c}g+="</td>\n<td width='50%'><span class=\"model-signature\" /></td>";return g})})();(function(){var t,k,l,u,x,q,n,m,p,o,j,r,v,s,i,d,b,B,h,g,f,e,c,a,A,z,w={}.hasOwnProperty,y=function(F,D){for(var C in D){if(w.call(D,C)){F[C]=D[C]}}function E(){this.constructor=F}E.prototype=D.prototype;F.prototype=new E();F.__super__=D.prototype;return F};v=(function(D){y(C,D);function C(){s=C.__super__.constructor.apply(this,arguments);return s}C.prototype.dom_id="swagger_ui";C.prototype.options=null;C.prototype.api=null;C.prototype.headerView=null;C.prototype.mainView=null;C.prototype.initialize=function(E){var F=this;if(E==null){E={}}if(E.dom_id!=null){this.dom_id=E.dom_id;delete E.dom_id}if($("#"+this.dom_id)==null){$("body").append('<div id="'+this.dom_id+'"></div>')}this.options=E;this.options.success=function(){return F.render()};this.options.progress=function(G){return F.showMessage(G)};this.options.failure=function(G){if(F.api&&F.api.isValid===false){log("not a valid 2.0 spec, loading legacy client");F.api=new SwaggerApi(F.options);return F.api.build()}else{return F.onLoadFailure(G)}};this.headerView=new u({el:$("#header")});return this.headerView.on("update-swagger-ui",function(G){return F.updateSwaggerUi(G)})};C.prototype.setOption=function(E,F){return this.options[E]=F};C.prototype.getOption=function(E){return this.options[E]};C.prototype.updateSwaggerUi=function(E){this.options.url=E.url;return this.load()};C.prototype.load=function(){var F,E;if((E=this.mainView)!=null){E.clear()}F=this.options.url;if(F.indexOf("http")!==0){F=this.buildUrl(window.location.href.toString(),F)}this.options.url=F;this.headerView.update(F);this.api=new SwaggerClient(this.options);return this.api.build()};C.prototype.collapseAll=function(){return Docs.collapseEndpointListForResource("")};C.prototype.listAll=function(){return Docs.collapseOperationsForResource("")};C.prototype.expandAll=function(){return Docs.expandOperationsForResource("")};C.prototype.render=function(){var E=this;this.showMessage("Finished Loading Resource Information. Rendering Swagger UI...");this.mainView=new x({model:this.api,el:$("#"+this.dom_id),swaggerOptions:this.options}).render();this.showMessage();switch(this.options.docExpansion){case"full":this.expandAll();break;case"list":this.listAll()}if(this.options.onComplete){this.options.onComplete(this.api,this)}return setTimeout(function(){return Docs.shebang()},400)};C.prototype.buildUrl=function(G,E){var F,H;log("base is "+G);if(E.indexOf("/")===0){H=G.split("/");G=H[0]+"//"+H[2];return G+E}else{F=G.length;if(G.indexOf("?")>-1){F=Math.min(F,G.indexOf("?"))}if(G.indexOf("#")>-1){F=Math.min(F,G.indexOf("#"))}G=G.substring(0,F);if(G.indexOf("/",G.length-1)!==-1){return G+E}return G+"/"+E}};C.prototype.showMessage=function(E){if(E==null){E=""}$("#message-bar").removeClass("message-fail");$("#message-bar").addClass("message-success");return $("#message-bar").html(E)};C.prototype.onLoadFailure=function(E){var F;if(E==null){E=""}$("#message-bar").removeClass("message-success");$("#message-bar").addClass("message-fail");F=$("#message-bar").html(E);if(this.options.onFailure!=null){this.options.onFailure(E)}return F};return C})(Backbone.Router);window.SwaggerUi=v;u=(function(D){y(C,D);function C(){i=C.__super__.constructor.apply(this,arguments);return i}C.prototype.events={"click #show-pet-store-icon":"showPetStore","click #show-wordnik-dev-icon":"showWordnikDev","click #explore":"showCustom","keyup #input_baseUrl":"showCustomOnKeyup","keyup #input_apiKey":"showCustomOnKeyup"};C.prototype.initialize=function(){};C.prototype.showPetStore=function(E){return this.trigger("update-swagger-ui",{url:"http://petstore.swagger.wordnik.com/api/api-docs"})};C.prototype.showWordnikDev=function(E){return this.trigger("update-swagger-ui",{url:"http://api.wordnik.com/v4/resources.json"})};C.prototype.showCustomOnKeyup=function(E){if(E.keyCode===13){return this.showCustom()}};C.prototype.showCustom=function(E){if(E!=null){E.preventDefault()}return this.trigger("update-swagger-ui",{url:$("#input_baseUrl").val(),apiKey:$("#input_apiKey").val()})};C.prototype.update=function(F,G,E){if(E==null){E=false}$("#input_baseUrl").val(F);if(E){return this.trigger("update-swagger-ui",{url:F})}};return C})(Backbone.View);x=(function(C){var D;y(E,C);function E(){h=E.__super__.constructor.apply(this,arguments);return h}D={alpha:function(G,F){return G.path.localeCompare(F.path)},method:function(G,F){return G.method.localeCompare(F.method)}};E.prototype.initialize=function(J){var I,H,G,F,K,L;if(J==null){J={}}this.model.auths=[];L=this.model.securityDefinitions;for(H in L){K=L[H];I={name:H,type:K.type,value:K};this.model.auths.push(I)}if(this.model.info&&this.model.info.license&&typeof this.model.info.license==="string"){G=this.model.info.license;F=this.model.info.licenseUrl;this.model.info.license={};this.model.info.license.name=G;this.model.info.license.url=F}if(!this.model.info){this.model.info={}}if(!this.model.info.version){this.model.info.version=this.model.apiVersion}if(this.model.swaggerVersion==="2.0"){if("validatorUrl" in J.swaggerOptions){return this.model.validatorUrl=J.swaggerOptions.validatorUrl}else{if(this.model.url.indexOf("localhost")>0){return this.model.validatorUrl=null}else{return this.model.validatorUrl="http://online.swagger.io/validator"}}}};E.prototype.render=function(){var K,N,F,H,G,L,I,M,O,J;if(this.model.securityDefinitions){for(G in this.model.securityDefinitions){K=this.model.securityDefinitions[G];if(K.type==="apiKey"&&$("#apikey_button").length===0){N=new t({model:K}).render().el;$(".auth_main_container").append(N)}if(K.type==="basicAuth"&&$("#basic_auth_button").length===0){N=new k({model:K}).render().el;$(".auth_main_container").append(N)}}}$(this.el).html(Handlebars.templates.main(this.model));I={};F=0;J=this.model.apisArray;for(M=0,O=J.length;M<O;M++){L=J[M];H=L.name;while(typeof I[H]!=="undefined"){H=H+"_"+F;F+=1}L.id=H;I[H]=L;this.addResource(L,this.model.auths)}return this};E.prototype.addResource=function(H,G){var F;H.id=H.id.replace(/\s/g,"_");F=new p({model:H,tagName:"li",id:"resource_"+H.id,className:"resource",auths:G,swaggerOptions:this.options.swaggerOptions});return $("#resources").append(F.render().el)};E.prototype.clear=function(){return $(this.el).html("")};return E})(Backbone.View);p=(function(D){y(C,D);function C(){g=C.__super__.constructor.apply(this,arguments);return g}C.prototype.initialize=function(E){if(E==null){E={}}this.auths=E.auths;if(""===this.model.description){return this.model.description=null}};C.prototype.render=function(){var F,K,H,G,I,E,J;$(this.el).html(Handlebars.templates.resource(this.model));H={};if(this.model.description){this.model.summary=this.model.description}J=this.model.operationsArray;for(I=0,E=J.length;I<E;I++){G=J[I];F=0;K=G.nickname;while(typeof H[K]!=="undefined"){K=K+"_"+F;F+=1}H[K]=G;G.nickname=K;G.parentId=this.model.id;this.addOperation(G)}$(".toggleEndpointList",this.el).click(this.callDocs.bind(this,"toggleEndpointListForResource"));$(".collapseResource",this.el).click(this.callDocs.bind(this,"collapseOperationsForResource"));$(".expandResource",this.el).click(this.callDocs.bind(this,"expandOperationsForResource"));return this};C.prototype.addOperation=function(E){var F;E.number=this.number;F=new q({model:E,tagName:"li",className:"endpoint",swaggerOptions:this.options.swaggerOptions,auths:this.auths});$(".endpoints",$(this.el)).append(F.render().el);return this.number++};C.prototype.callDocs=function(F,E){E.preventDefault();return Docs[F](E.currentTarget.getAttribute("data-id"))};return C})(Backbone.View);q=(function(D){y(C,D);function C(){f=C.__super__.constructor.apply(this,arguments);return f}C.prototype.invocationUrl=null;C.prototype.events={"submit .sandbox":"submitOperation","click .submit":"submitOperation","click .response_hider":"hideResponse","click .toggleOperation":"toggleOperationContent","mouseenter .api-ic":"mouseEnter","mouseout .api-ic":"mouseExit"};C.prototype.initialize=function(E){if(E==null){E={}}this.auths=E.auths;return this};C.prototype.mouseEnter=function(J){var H,I,M,F,E,N,K,G,O,L;H=$(J.currentTarget.parentNode).find("#api_information_panel");O=J.pageX;L=J.pageY;N=$(window).scrollLeft();K=$(window).scrollTop();F=N+$(window).width();E=K+$(window).height();G=H.width();I=H.height();if(O+G>F){O=F-G}if(O<N){O=N}if(L+I>E){L=E-I}if(L<K){L=K}M={};M.top=L;M.left=O;H.css(M);return $(J.currentTarget.parentNode).find("#api_information_panel").show()};C.prototype.mouseExit=function(E){return $(E.currentTarget.parentNode).find("#api_information_panel").hide()};C.prototype.render=function(){var al,R,aj,F,W,V,af,S,ab,H,Z,G,U,X,ad,ak,E,ao,Y,aa,ai,ah,ag,ae,T,N,L,J,I,ac,an,am,Q,P,O,M,K;V=true;if(!V){this.model.isReadOnly=true}this.model.description=this.model.description||this.model.notes;if(this.model.description){this.model.description=this.model.description.replace(/(?:\r\n|\r|\n)/g,"<br />")}this.model.oauth=null;if(this.model.authorizations){if(Array.isArray(this.model.authorizations)){Q=this.model.authorizations;for(ai=0,T=Q.length;ai<T;ai++){aj=Q[ai];for(S in aj){R=aj[S];for(al in this.auths){R=this.auths[al];if(R.type==="oauth2"){this.model.oauth={};this.model.oauth.scopes=[];P=R.value.scopes;for(af in P){Y=P[af];ab={scope:af,description:Y};this.model.oauth.scopes.push(ab)}}}}}}else{O=this.model.authorizations;for(af in O){Y=O[af];if(af==="oauth2"){if(this.model.oauth===null){this.model.oauth={}}if(this.model.oauth.scopes===void 0){this.model.oauth.scopes=[]}for(ah=0,N=Y.length;ah<N;ah++){ab=Y[ah];this.model.oauth.scopes.push(ab)}}}}}if(typeof this.model.responses!=="undefined"){this.model.responseMessages=[];M=this.model.responses;for(F in M){aa=M[F];X=null;ad=this.model.responses[F].schema;if(ad&&ad["$ref"]){X=ad["$ref"];if(X.indexOf("#/definitions/")===0){X=X.substring("#/definitions/".length)}}this.model.responseMessages.push({code:F,message:aa.description,responseModel:X})}}if(typeof this.model.responseMessages==="undefined"){this.model.responseMessages=[]}$(this.el).html(Handlebars.templates.operation(this.model));if(this.model.responseClassSignature&&this.model.responseClassSignature!=="string"){ak={sampleJSON:this.model.responseSampleJSON,isParam:false,signature:this.model.responseClassSignature};U=new j({model:ak,tagName:"div"});$(".model-signature",$(this.el)).append(U.render().el)}else{this.model.responseClassSignature="string";$(".model-signature",$(this.el)).html(this.model.type)}W={isParam:false};W.consumes=this.model.consumes;W.produces=this.model.produces;K=this.model.parameters;for(ag=0,L=K.length;ag<L;ag++){H=K[ag];ao=H.type||H.dataType;if(typeof ao==="undefined"){X=H.schema;if(X&&X["$ref"]){Z=X["$ref"];if(Z.indexOf("#/definitions/")===0){ao=Z.substring("#/definitions/".length)}else{ao=Z}}}if(ao&&ao.toLowerCase()==="file"){if(!W.consumes){W.consumes="multipart/form-data"}}H.type=ao}G=new o({model:W});$(".response-content-type",$(this.el)).append(G.render().el);an=this.model.parameters;for(ae=0,J=an.length;ae<J;ae++){H=an[ae];this.addParameter(H,W.consumes)}am=this.model.responseMessages;for(ac=0,I=am.length;ac<I;ac++){E=am[ac];this.addStatusCode(E)}return this};C.prototype.addParameter=function(G,E){var F;G.consumes=E;F=new m({model:G,tagName:"tr",readOnly:this.model.isReadOnly});return $(".operation-params",$(this.el)).append(F.render().el)};C.prototype.addStatusCode=function(F){var E;E=new r({model:F,tagName:"tr"});return $(".operation-status",$(this.el)).append(E.render().el)};C.prototype.submitOperation=function(S){var U,K,R,H,M,E,N,Q,P,O,T,J,G,L,I,F;if(S!=null){S.preventDefault()}K=$(".sandbox",$(this.el));U=true;K.find("input.required").each(function(){var V=this;$(this).removeClass("error");if(jQuery.trim($(this).val())===""){$(this).addClass("error");$(this).wiggle({callback:function(){return $(V).focus()}});return U=false}});K.find("textarea.required").each(function(){var V=this;$(this).removeClass("error");if(jQuery.trim($(this).val())===""){$(this).addClass("error");$(this).wiggle({callback:function(){return $(V).focus()}});return U=false}});if(U){H={};E={parent:this};R=false;L=K.find("input");for(Q=0,T=L.length;Q<T;Q++){M=L[Q];if((M.value!=null)&&jQuery.trim(M.value).length>0){H[M.name]=M.value}if(M.type==="file"){R=true}}I=K.find("textarea");for(P=0,J=I.length;P<J;P++){M=I[P];if((M.value!=null)&&jQuery.trim(M.value).length>0){H[M.name]=M.value}}F=K.find("select");for(O=0,G=F.length;O<G;O++){M=F[O];N=this.getSelectedValue(M);if((N!=null)&&jQuery.trim(N).length>0){H[M.name]=N}}E.responseContentType=$("div select[name=responseContentType]",$(this.el)).val();E.requestContentType=$("div select[name=parameterContentType]",$(this.el)).val();$(".response_throbber",$(this.el)).show();if(R){return this.handleFileUpload(H,K)}else{return this.model["do"](H,E,this.showCompleteStatus,this.showErrorStatus,this)}}};C.prototype.success=function(E,F){return F.showCompleteStatus(E)};C.prototype.handleFileUpload=function(V,M){var Q,L,G,R,P,O,T,N,K,J,H,U,Y,X,W,I,F,E,Z,S=this;I=M.serializeArray();for(N=0,U=I.length;N<U;N++){R=I[N];if((R.value!=null)&&jQuery.trim(R.value).length>0){V[R.name]=R.value}}Q=new FormData();T=0;F=this.model.parameters;for(K=0,Y=F.length;K<Y;K++){O=F[K];if(O.paramType==="form"){if(O.type.toLowerCase()!=="file"&&V[O.name]!==void 0){Q.append(O.name,V[O.name])}}}G={};E=this.model.parameters;for(J=0,X=E.length;J<X;J++){O=E[J];if(O.paramType==="header"){G[O.name]=V[O.name]}}Z=M.find('input[type~="file"]');for(H=0,W=Z.length;H<W;H++){L=Z[H];if(typeof L.files[0]!=="undefined"){Q.append($(L).attr("name"),L.files[0]);T+=1}}this.invocationUrl=this.model.supportHeaderParams()?(G=this.model.getHeaderParams(V),this.model.urlify(V,false)):this.model.urlify(V,true);$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(this.invocationUrl);P={type:this.model.method,url:this.invocationUrl,headers:G,data:Q,dataType:"json",contentType:false,processData:false,error:function(ab,ac,aa){return S.showErrorStatus(S.wrap(ab),S)},success:function(aa){return S.showResponse(aa,S)},complete:function(aa){return S.showCompleteStatus(S.wrap(aa),S)}};if(window.authorizations){window.authorizations.apply(P)}if(T===0){P.data.append("fake","true")}jQuery.ajax(P);return false};C.prototype.wrap=function(I){var G,J,L,F,K,H,E;L={};J=I.getAllResponseHeaders().split("\r");for(H=0,E=J.length;H<E;H++){F=J[H];G=F.split(":");if(G[0]!==void 0&&G[1]!==void 0){L[G[0].trim()]=G[1].trim()}}K={};K.content={};K.content.data=I.responseText;K.headers=L;K.request={};K.request.url=this.invocationUrl;K.status=I.status;return K};C.prototype.getSelectedValue=function(E){var H,G,J,F,I;if(!E.multiple){return E.value}else{G=[];I=E.options;for(J=0,F=I.length;J<F;J++){H=I[J];if(H.selected){G.push(H.value)}}if(G.length>0){return G}else{return null}}};C.prototype.hideResponse=function(E){if(E!=null){E.preventDefault()}$(".response",$(this.el)).slideUp();return $(".response_hider",$(this.el)).fadeOut()};C.prototype.showResponse=function(E){var F;F=JSON.stringify(E,null,"\t").replace(/\n/g,"<br>");return $(".response_body",$(this.el)).html(escape(F))};C.prototype.showErrorStatus=function(F,E){return E.showStatus(F)};C.prototype.showCompleteStatus=function(F,E){return E.showStatus(F)};C.prototype.formatXml=function(L){var H,K,F,M,R,N,G,E,P,Q,J,I,O;E=/(>)(<)(\/*)/g;Q=/[ ]*(.*)[ ]+\n/g;H=/(<.+>)(.+\n)/g;L=L.replace(E,"$1\n$2$3").replace(Q,"$1\n").replace(H,"$1\n$2");G=0;K="";R=L.split("\n");F=0;M="other";P={"single->single":0,"single->closing":-1,"single->opening":0,"single->other":0,"closing->single":0,"closing->closing":-1,"closing->opening":0,"closing->other":0,"opening->single":1,"opening->closing":0,"opening->opening":1,"opening->other":1,"other->single":0,"other->closing":-1,"other->opening":0,"other->other":0};J=function(X){var T,S,V,Z,W,U,Y;U={single:Boolean(X.match(/<.+\/>/)),closing:Boolean(X.match(/<\/.+>/)),opening:Boolean(X.match(/<[^!?].*>/))};W=((function(){var aa;aa=[];for(V in U){Y=U[V];if(Y){aa.push(V)}}return aa})())[0];W=W===void 0?"other":W;T=M+"->"+W;M=W;Z="";F+=P[T];Z=((function(){var ab,ac,aa;aa=[];for(S=ab=0,ac=F;0<=ac?ab<ac:ab>ac;S=0<=ac?++ab:--ab){aa.push(" ")}return aa})()).join("");if(T==="opening->closing"){return K=K.substr(0,K.length-1)+X+"\n"}else{return K+=Z+X+"\n"}};for(I=0,O=R.length;I<O;I++){N=R[I];J(N)}return K};C.prototype.showStatus=function(J){var G,N,P,M,H,Q,E,I,L,K,F;if(J.content===void 0){N=J.data;F=J.url}else{N=J.content.data;F=J.request.url}H=J.headers;P=null;if(H){P=H["Content-Type"]||H["content-type"];if(P){P=P.split(";")[0].trim()}}if(!N){G=$("<code />").text("no content");I=$('<pre class="json" />').append(G)}else{if(P==="application/json"||/\+json$/.test(P)){Q=null;try{Q=JSON.stringify(JSON.parse(N),null," ")}catch(O){M=O;Q="can't parse JSON. Raw result:\n\n"+N}G=$("<code />").text(Q);I=$('<pre class="json" />').append(G)}else{if(P==="application/xml"||/\+xml$/.test(P)){G=$("<code />").text(this.formatXml(N));I=$('<pre class="xml" />').append(G)}else{if(P==="text/html"){G=$("<code />").html(_.escape(N));I=$('<pre class="xml" />').append(G)}else{if(/^image\//.test(P)){I=$("<img>").attr("src",F)}else{G=$("<code />").text(N);I=$('<pre class="json" />').append(G)}}}}}L=I;$(".request_url",$(this.el)).html("<pre></pre>");$(".request_url pre",$(this.el)).text(F);$(".response_code",$(this.el)).html("<pre>"+J.status+"</pre>");$(".response_body",$(this.el)).html(L);$(".response_headers",$(this.el)).html("<pre>"+_.escape(JSON.stringify(J.headers,null," ")).replace(/\n/g,"<br>")+"</pre>");$(".response",$(this.el)).slideDown();$(".response_hider",$(this.el)).show();$(".response_throbber",$(this.el)).hide();K=$(".response_body",$(this.el))[0];E=this.options.swaggerOptions;if(E.highlightSizeThreshold&&J.data.length>E.highlightSizeThreshold){return K}else{return hljs.highlightBlock(K)}};C.prototype.toggleOperationContent=function(){var E;E=$("#"+Docs.escapeResourceName(this.model.parentId+"_"+this.model.nickname+"_content"));if(E.is(":visible")){return Docs.collapseOperation(E)}else{return Docs.expandOperation(E)}};return C})(Backbone.View);r=(function(D){y(C,D);function C(){e=C.__super__.constructor.apply(this,arguments);return e}C.prototype.initialize=function(){};C.prototype.render=function(){var F,E,G;G=this.template();$(this.el).html(G(this.model));if(swaggerUi.api.models.hasOwnProperty(this.model.responseModel)){F={sampleJSON:JSON.stringify(swaggerUi.api.models[this.model.responseModel].createJSONSample(),null,2),isParam:false,signature:swaggerUi.api.models[this.model.responseModel].getMockSignature()};E=new j({model:F,tagName:"div"});$(".model-signature",this.$el).append(E.render().el)}else{$(".model-signature",this.$el).html("")}return this};C.prototype.template=function(){return Handlebars.templates.status_code};return C})(Backbone.View);m=(function(D){y(C,D);function C(){c=C.__super__.constructor.apply(this,arguments);return c}C.prototype.initialize=function(){return Handlebars.registerHelper("isArray",function(F,E){if(F.type.toLowerCase()==="array"||F.allowMultiple){return E.fn(this)}else{return E.inverse(this)}})};C.prototype.render=function(){var E,F,I,G,J,H,M,N,L,K;K=this.model.type||this.model.dataType;if(typeof K==="undefined"){H=this.model.schema;if(H&&H["$ref"]){G=H["$ref"];if(G.indexOf("#/definitions/")===0){K=G.substring("#/definitions/".length)}else{K=G}}}this.model.type=K;this.model.paramType=this.model["in"]||this.model.paramType;if(this.model.paramType==="body"){this.model.isBody=true}if(K&&K.toLowerCase()==="file"){this.model.isFile=true}this.model["default"]=this.model["default"]||this.model.defaultValue;if(this.model.allowableValues){this.model.isList=true}L=this.template();$(this.el).html(L(this.model));M={sampleJSON:this.model.sampleJSON,isParam:true,signature:this.model.signature};if(this.model.sampleJSON){N=new j({model:M,tagName:"div"});$(".model-signature",$(this.el)).append(N.render().el)}else{$(".model-signature",$(this.el)).html(this.model.signature)}F=false;if(this.model.isBody){F=true}E={isParam:F};E.consumes=this.model.consumes;if(F){I=new n({model:E});$(".parameter-content-type",$(this.el)).append(I.render().el)}else{J=new o({model:E});$(".response-content-type",$(this.el)).append(J.render().el)}return this};C.prototype.template=function(){if(this.model.isList){return Handlebars.templates.param_list}else{if(this.options.readOnly){if(this.model.required){return Handlebars.templates.param_readonly_required}else{return Handlebars.templates.param_readonly}}else{if(this.model.required){return Handlebars.templates.param_required}else{return Handlebars.templates.param}}}};return C})(Backbone.View);j=(function(D){y(C,D);function C(){a=C.__super__.constructor.apply(this,arguments);return a}C.prototype.events={"click a.description-link":"switchToDescription","click a.snippet-link":"switchToSnippet","mousedown .snippet":"snippetToTextArea"};C.prototype.initialize=function(){};C.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));this.switchToSnippet();this.isParam=this.model.isParam;if(this.isParam){$(".notice",$(this.el)).text("Click to set as parameter value")}return this};C.prototype.template=function(){return Handlebars.templates.signature};C.prototype.switchToDescription=function(E){if(E!=null){E.preventDefault()}$(".snippet",$(this.el)).hide();$(".description",$(this.el)).show();$(".description-link",$(this.el)).addClass("selected");return $(".snippet-link",$(this.el)).removeClass("selected")};C.prototype.switchToSnippet=function(E){if(E!=null){E.preventDefault()}$(".description",$(this.el)).hide();$(".snippet",$(this.el)).show();$(".snippet-link",$(this.el)).addClass("selected");return $(".description-link",$(this.el)).removeClass("selected")};C.prototype.snippetToTextArea=function(E){var F;if(this.isParam){if(E!=null){E.preventDefault()}F=$("textarea",$(this.el.parentNode.parentNode.parentNode));if($.trim(F.val())===""){return F.val(this.model.sampleJSON)}}};return C})(Backbone.View);l=(function(C){y(D,C);function D(){A=D.__super__.constructor.apply(this,arguments);return A}D.prototype.initialize=function(){};D.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));$("label[for=contentType]",$(this.el)).text("Response Content Type");return this};D.prototype.template=function(){return Handlebars.templates.content_type};return D})(Backbone.View);o=(function(C){y(D,C);function D(){z=D.__super__.constructor.apply(this,arguments);return z}D.prototype.initialize=function(){};D.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));$("label[for=responseContentType]",$(this.el)).text("Response Content Type");return this};D.prototype.template=function(){return Handlebars.templates.response_content_type};return D})(Backbone.View);n=(function(D){y(C,D);function C(){d=C.__super__.constructor.apply(this,arguments);return d}C.prototype.initialize=function(){};C.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));$("label[for=parameterContentType]",$(this.el)).text("Parameter content type:");return this};C.prototype.template=function(){return Handlebars.templates.parameter_content_type};return C})(Backbone.View);t=(function(D){y(C,D);function C(){b=C.__super__.constructor.apply(this,arguments);return b}C.prototype.initialize=function(){};C.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));return this};C.prototype.events={"click #apikey_button":"toggleApiKeyContainer","click #apply_api_key":"applyApiKey"};C.prototype.applyApiKey=function(){var E;window.authorizations.add(this.model.name,new ApiKeyAuthorization(this.model.name,$("#input_apiKey_entry").val(),this.model["in"]));window.swaggerUi.load();return E=$("#apikey_container").show()};C.prototype.toggleApiKeyContainer=function(){var E;if($("#apikey_container").length>0){E=$("#apikey_container").first();if(E.is(":visible")){return E.hide()}else{$(".auth_container").hide();return E.show()}}};C.prototype.template=function(){return Handlebars.templates.apikey_button_view};return C})(Backbone.View);k=(function(D){y(C,D);function C(){B=C.__super__.constructor.apply(this,arguments);return B}C.prototype.initialize=function(){};C.prototype.render=function(){var E;E=this.template();$(this.el).html(E(this.model));return this};C.prototype.events={"click #basic_auth_button":"togglePasswordContainer","click #apply_basic_auth":"applyPassword"};C.prototype.applyPassword=function(){var F,E,G;console.log("applying password");G=$(".input_username").val();E=$(".input_password").val();window.authorizations.add(this.model.type,new PasswordAuthorization("basic",G,E));window.swaggerUi.load();return F=$("#basic_auth_container").hide()};C.prototype.togglePasswordContainer=function(){var E;if($("#basic_auth_container").length>0){E=$("#basic_auth_container").show();if(E.is(":visible")){return E.slideUp()}else{$(".auth_container").hide();return E.show()}}};C.prototype.template=function(){return Handlebars.templates.basic_auth_button_view};return C})(Backbone.View)}).call(this);
{
"name": "swagger-tools",
"version": "0.6.13",
"version": "0.7.0",
"description": "Various tools for using and integrating with Swagger.",

@@ -43,3 +43,3 @@ "main": "index.js",

"brfs": "^1.2.0",
"browserify": "^5.12.1",
"browserify": "^5.13.1",
"connect": "^3.1.0",

@@ -59,13 +59,15 @@ "exposify": "^0.2.0",

"async": "^0.9.0",
"commander": "^2.3.0",
"jjv": "^1.0.0",
"jjve": "^0.4.0",
"commander": "^2.5.0",
"json-refs": "^0.1.4",
"lodash": "^2.4.1",
"parseurl": "^1.2.0",
"path-to-regexp": "^0.2.3",
"serve-static": "^1.6.3",
"path-to-regexp": "^0.2.5",
"serve-static": "^1.7.1",
"spark-md5": "0.0.5",
"string": "^2.1.0",
"traverse": "^0.6.6"
"superagent": "^0.21.0",
"traverse": "^0.6.6",
"yamljs": "^0.2.1",
"z-schema": "^3.1.5"
}
}
The project provides various tools for integrating and interacting with Swagger. This project is in its infancy but
what is within the repository should be fully tested and reusable. Please visit the [issue tracker][project-issues] to
see what issues we are aware of and what features/enhancements we are working on.
see what issues we are aware of and what features/enhancements we are working on. Otherwise, feel free to review the
[Release Notes][release-notes] to see what is new and improved.

@@ -17,3 +18,3 @@ ## Project Badges

* [1.2][swagger-docs-v1_2]
* [2.0 (WIP)][swagger-docs-v2_0]
* [2.0][swagger-docs-v2_0]

@@ -27,2 +28,3 @@ ## Features

* Connect middleware for adding pertinent Swagger information to your requests _(Node only)_
* Connect middleware for wiring up security handlers for requests based on Swagger documentation _(Node only)_
* Connect middleware for wiring request handlers to requests based on Swagger documentation _(Node only)_

@@ -58,2 +60,3 @@ * Connect middleware for serving your Swagger documents and [Swagger UI][swagger-ui] _(Node only)_

[quick-start]: https://github.com/apigee-127/swagger-tools/blob/master/docs/QuickStart.md
[release-notes]: https://github.com/apigee-127/swagger-tools/blob/master/RELEASE_NOTES.md
[swagger]: https://helloreverb.com/developers/swagger

@@ -60,0 +63,0 @@ [swagger-docs-v1_2]: https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md

@@ -57,5 +57,6 @@ {

"format": "mime-type"
}
},
"uniqueItems": true
}
}
}

@@ -10,3 +10,3 @@ {

"properties": {
"method": { "enum": [ "GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" ] },
"method": { "enum": [ "GET", "HEAD", "POST", "PUT", "PATCH", "DELETE", "OPTIONS" ] },
"summary": { "type": "string", "maxLength": 120 },

@@ -62,5 +62,6 @@ "notes": { "type": "string" },

"format": "mime-type"
}
},
"uniqueItems": true
}
}
}

Sorry, the diff of this file is not supported yet

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

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc