Added Path object and related APIs

This commit is contained in:
Jeremy Whitlock 2015-08-24 20:49:15 -07:00
Родитель ed7fcf0d07
Коммит fe6594dab5
11 изменённых файлов: 1310 добавлений и 373 удалений

Просмотреть файл

@ -28,8 +28,8 @@ bower install sway --save
The standalone binaries come in two flavors:
* [sway-standalone.js](https://raw.github.com/apigee-127/sway/master/browser/sway.js): _3,944kb_, full source and source maps
* [sway-standalone-min.js](https://raw.github.com/apigee-127/sway/master/browser/sway-min.js): _580kb_, minified, compressed and no source map
* [sway-standalone.js](https://raw.github.com/apigee-127/sway/master/browser/sway.js): _3,980kb_, full source and source maps
* [sway-standalone-min.js](https://raw.github.com/apigee-127/sway/master/browser/sway-min.js): _584kb_, minified, compressed and no source map
**Note:** I realize these browser binaries are not small. For the most part, this is due to a library we are using for
creating mock/sample parameters/responses. [json-schema-faker](https://github.com/pateketrueke/json-schema-faker) uses

Просмотреть файл

@ -1,5 +1,9 @@
## Release Notes
### TBD
* Added `Path` object, `SwaggerApi#getPath(reqOrPath)` and `SwaggerApi#getPaths()`
### v0.1.0 (2015-08-12)
* Initial release

10
browser/sway-min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

24
browser/sway-standalone-min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -6,6 +6,8 @@
<dd></dd>
<dt><a href="#Parameter">Parameter</a></dt>
<dd></dd>
<dt><a href="#Path">Path</a></dt>
<dd></dd>
<dt><a href="#SwaggerApi">SwaggerApi</a></dt>
<dd></dd>
</dl>
@ -24,29 +26,43 @@
<a name="Operation"></a>
## Operation
**Kind**: global class
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| api | <code>[SwaggerApi](#SwaggerApi)</code> | The Swagger API object |
| definition | <code>object</code> | The operation definition |
| method | <code>string</code> | The HTTP method for this operation |
| pathObject | <code>[Path](#Path)</code> | The Path object |
| parameterObjects | <code>[Array.&lt;Parameter&gt;](#Parameter)</code> | The Parameter objects |
| ptr | <code>string</code> | The JSON Pointer to the operation |
| securityDefinitions | <code>object</code> | The security definitions used by this operation |
* [Operation](#Operation)
* [new Operation(api, path, method, ptr, definition, regexp)](#new_Operation_new)
* [new Operation(api, pathObject, method, ptr, definition)](#new_Operation_new)
* [.getParameters()](#Operation+getParameters) ⇒ <code>[Array.&lt;Parameter&gt;](#Parameter)</code>
* [.getResponseExample(codeOrMimeType, [mimeType])](#Operation+getResponseExample) ⇒ <code>string</code>
* [.getResponseSchema([code])](#Operation+getResponseSchema) ⇒ <code>object</code>
* [.getResponseSample([code])](#Operation+getResponseSample) ⇒ <code>\*</code>
<a name="new_Operation_new"></a>
### new Operation(api, path, method, ptr, definition, regexp)
### new Operation(api, pathObject, method, ptr, definition)
The Swagger Operation object.
**Note:** Do not use directly.
**Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
object.
| Param | Type | Description |
| --- | --- | --- |
| api | <code>[SwaggerApi](#SwaggerApi)</code> | The Swagger API object |
| path | <code>string</code> | The operation path |
| pathObject | <code>[Path](#Path)</code> | The Path object |
| method | <code>string</code> | The operation method |
| ptr | <code>string</code> | The JSON Pointer to the operation |
| definition | <code>object</code> | The operation definition |
| regexp | <code>regexp</code> | The regexp used to match request paths against this operation |
<a name="Operation+getParameters"></a>
### operation.getParameters() ⇒ <code>[Array.&lt;Parameter&gt;](#Parameter)</code>
@ -114,6 +130,8 @@ Returns a sample value based on the requested code or the default response if no
### new ParameterValue(parameter, raw)
Object representing a parameter value.
**Note:** Do not use directly.
| Param | Type | Description |
| --- | --- | --- |
@ -123,23 +141,36 @@ Object representing a parameter value.
<a name="Parameter"></a>
## Parameter
**Kind**: global class
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| definition | <code>object</code> | The parameter definition |
| operationObject | <code>[Operation](#Operation)</code> | The Operation object (Can be undefined for path-level parameters) |
| pathObject | <code>[Path](#Path)</code> | The Path object |
| ptr | <code>string</code> | The JSON Pointer to the parameter definition |
| schema | <code>object</code> | The JSON Schema for the parameter |
* [Parameter](#Parameter)
* [new Parameter(operation, ptr, definition, schema)](#new_Parameter_new)
* [new Parameter(opOrPath, ptr, definition, schema)](#new_Parameter_new)
* [.getSchema()](#Parameter+getSchema) ⇒ <code>object</code>
* [.getSample()](#Parameter+getSample) ⇒ <code>\*</code>
* [.getValue(req)](#Parameter+getValue) ⇒ <code>[ParameterValue](#ParameterValue)</code>
<a name="new_Parameter_new"></a>
### new Parameter(operation, ptr, definition, schema)
### new Parameter(opOrPath, ptr, definition, schema)
The Swagger Parameter object.
**Note:** Do not use directly.
**Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
object.
| Param | Type | Description |
| --- | --- | --- |
| operation | <code>[Operation](#Operation)</code> | The Swagger Operation object |
| opOrPath | <code>[Operation](#Operation)</code> &#124; <code>[Path](#Path)</code> | The Operation or Path object |
| ptr | <code>string</code> | The JSON Pointer to the parameter |
| definition | <code>object</code> | The parameter definition |
| schema | <code>object</code> | The JSON Schema for the parameter |
@ -184,9 +215,100 @@ property.
| --- | --- | --- |
| req | <code>object</code> | The http client request *(or equivalent)* |
<a name="Path"></a>
## Path
**Kind**: global class
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| api | <code>[SwaggerApi](#SwaggerApi)</code> | The Swagger API object |
| definition | <code>object</code> | The path definition |
| operationObjects | <code>[Array.&lt;Operation&gt;](#Operation)</code> | The operation objects |
| parameterObjects | <code>[Array.&lt;Parameter&gt;](#Parameter)</code> | The path-level parameter objects |
| path | <code>string</code> | The path string |
| ptr | <code>ptr</code> | The JSON Pointer to the path |
| regexp | <code>regexp</code> | The regexp used to match request paths against this path |
* [Path](#Path)
* [new Path(api, path, ptr, definition, regexp)](#new_Path_new)
* [.getOperation(method)](#Path+getOperation) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
* [.getOperations()](#Path+getOperations) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
* [.getOperationsByTag(tag)](#Path+getOperationsByTag) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
* [.getParameters()](#Path+getParameters) ⇒ <code>[Array.&lt;Parameter&gt;](#Parameter)</code>
<a name="new_Path_new"></a>
### new Path(api, path, ptr, definition, regexp)
The Path object.
**Note:** Do not use directly.
**Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
object.
| Param | Type | Description |
| --- | --- | --- |
| api | <code>[SwaggerApi](#SwaggerApi)</code> | The Swagger API object |
| path | <code>string</code> | The path string |
| ptr | <code>ptr</code> | The JSON Pointer to the path |
| definition | <code>object</code> | The path definition |
| regexp | <code>regexp</code> | The regexp used to match request paths against this path |
<a name="Path+getOperation"></a>
### path.getOperation(method) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
Return the operation for this path and method.
**Kind**: instance method of <code>[Path](#Path)</code>
**Returns**: <code>[Array.&lt;Operation&gt;](#Operation)</code> - The Operation objects for this path and method or undefined if there is no operation for the
provided method.
| Param | Type | Description |
| --- | --- | --- |
| method | <code>string</code> | The method |
<a name="Path+getOperations"></a>
### path.getOperations() ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
Return the operations for this path.
**Kind**: instance method of <code>[Path](#Path)</code>
**Returns**: <code>[Array.&lt;Operation&gt;](#Operation)</code> - The Operation objects for this path.
<a name="Path+getOperationsByTag"></a>
### path.getOperationsByTag(tag) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
Return the operations for this path and tag.
**Kind**: instance method of <code>[Path](#Path)</code>
**Returns**: <code>[Array.&lt;Operation&gt;](#Operation)</code> - The Operation objects for this path and tag
| Param | Type | Description |
| --- | --- | --- |
| tag | <code>string</code> | The tag |
<a name="Path+getParameters"></a>
### path.getParameters() ⇒ <code>[Array.&lt;Parameter&gt;](#Parameter)</code>
Return the parameters for this path.
**Kind**: instance method of <code>[Path](#Path)</code>
**Returns**: <code>[Array.&lt;Parameter&gt;](#Parameter)</code> - The Parameter objects for this path.
<a name="SwaggerApi"></a>
## SwaggerApi
**Kind**: global class
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| customValidators | <code>Array.&lt;function()&gt;</code> | The array of custom validators |
| definition | <code>object</code> | The API definition |
| documentation | <code>string</code> | The URL to the Swagger documentation |
| errors | <code>Array.&lt;object&gt;</code> | The validation errors or undefined if validation has not run |
| pathObjects | <code>[Array.&lt;Path&gt;](#Path)</code> | The unique path objects |
| options | <code>object</code> | The options passed to the constructor |
| references | <code>object</code> | The reference metadata |
| resolved | <code>object</code> | The fully resolved API definition |
| version | <code>string</code> | The Swagger API version |
| warnings | <code>Array.&lt;object&gt;</code> | The validation warnings or undefined if validation has not run |
* [SwaggerApi](#SwaggerApi)
* [new SwaggerApi(plugin, definition, resolved, references, options)](#new_SwaggerApi_new)
@ -195,6 +317,8 @@ property.
* [.getOperation(pathOrReq, [method])](#SwaggerApi+getOperation) ⇒ <code>[Operation](#Operation)</code>
* [.getOperations([path])](#SwaggerApi+getOperations) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
* [.getOperationsByTag([tag])](#SwaggerApi+getOperationsByTag) ⇒ <code>[Array.&lt;Operation&gt;](#Operation)</code>
* [.getPath(pathOrReq)](#SwaggerApi+getPath) ⇒ <code>[Path](#Path)</code>
* [.getPaths()](#SwaggerApi+getPaths) ⇒ <code>[Array.&lt;Path&gt;](#Path)</code>
* [.registerValidator(validator)](#SwaggerApi+registerValidator)
* [.validate()](#SwaggerApi+validate) ⇒ <code>boolean</code>
@ -204,6 +328,9 @@ The Swagger API object.
**Note:** Do not use directly.
**Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
object.
| Param | Type | Description |
| --- | --- | --- |
@ -269,6 +396,30 @@ Returns all operations for the provided tag.
| --- | --- | --- |
| [tag] | <code>string</code> | The Swagger tag |
<a name="SwaggerApi+getPath"></a>
### swaggerApi.getPath(pathOrReq) ⇒ <code>[Path](#Path)</code>
Returns the path object for the given path or request.
**Note:** Below is the list of `reqOrPath` properties used when `reqOrPath` is an `http.ClientRequest`
*(or equivalent)*:
* `url`
*(See: [https://nodejs.org/api/http.html#http_class_http_clientrequest](https://nodejs.org/api/http.html#http_class_http_clientrequest))*
**Kind**: instance method of <code>[SwaggerApi](#SwaggerApi)</code>
**Returns**: <code>[Path](#Path)</code> - The corresponding Path object for the requested path or request.
| Param | Type | Description |
| --- | --- | --- |
| pathOrReq | <code>string</code> &#124; <code>object</code> | The Swagger path string or the http client request *(or equivalent)* |
<a name="SwaggerApi+getPaths"></a>
### swaggerApi.getPaths() ⇒ <code>[Array.&lt;Path&gt;](#Path)</code>
Returns all path objects for the Swagger API.
**Kind**: instance method of <code>[SwaggerApi](#SwaggerApi)</code>
**Returns**: <code>[Array.&lt;Path&gt;](#Path)</code> - The Path objects
<a name="SwaggerApi+registerValidator"></a>
### swaggerApi.registerValidator(validator)
Registers a validator.

Просмотреть файл

@ -28,8 +28,8 @@ bower install sway --save
The standalone binaries come in two flavors:
* [sway-standalone.js](https://raw.github.com/apigee-127/sway/master/browser/sway.js): _3,944kb_, full source and source maps
* [sway-standalone-min.js](https://raw.github.com/apigee-127/sway/master/browser/sway-min.js): _580kb_, minified, compressed and no source map
* [sway-standalone.js](https://raw.github.com/apigee-127/sway/master/browser/sway.js): _3,980kb_, full source and source maps
* [sway-standalone-min.js](https://raw.github.com/apigee-127/sway/master/browser/sway-min.js): _584kb_, minified, compressed and no source map
**Note:** I realize these browser binaries are not small. For the most part, this is due to a library we are using for
creating mock/sample parameters/responses. [json-schema-faker](https://github.com/pateketrueke/json-schema-faker) uses

Просмотреть файл

@ -154,22 +154,31 @@ function convertValue (schema, collectionFormat, value) {
*
* **Note:** Do not use directly.
*
* **Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
* object.
*
* @param {SwaggerApi} api - The Swagger API object
* @param {string} path - The operation path
* @param {Path} pathObject - The Path object
* @param {string} method - The operation method
* @param {string} ptr - The JSON Pointer to the operation
* @param {object} definition - The operation definition
* @param {regexp} regexp - The regexp used to match request paths against this operation
*
* @property {SwaggerApi} api - The Swagger API object
* @property {object} definition - The operation definition
* @property {string} method - The HTTP method for this operation
* @property {Path} pathObject - The Path object
* @property {Parameter[]} parameterObjects - The Parameter objects
* @property {string} ptr - The JSON Pointer to the operation
* @property {object} securityDefinitions - The security definitions used by this operation
*
* @constructor
*/
function Operation (api, path, method, ptr, definition, regexp) {
function Operation (api, pathObject, method, ptr, definition) {
this.api = api;
this.path = path;
this.pathObject = pathObject;
this.method = method;
this.ptr = ptr;
this.definition = definition;
this.regexp = regexp;
// Assign Swagger definition properties to the operation for easy access
_.assign(this, definition);
@ -288,6 +297,8 @@ Operation.prototype.getResponseSample = function (code) {
/**
* Object representing a parameter value.
*
* **Note:** Do not use directly.
*
* @param {Parameter} parameter - The Parameter Object
* @param {*} raw - The original/raw value
*
@ -345,7 +356,7 @@ function ParameterValue (parameter, raw) {
// Validate against JSON Schema
result = helpers.validateAgainstSchema(helpers.createJSONValidator({
formatValidators: parameter.operation.api.plugin.customFormatValidators
formatValidators: parameter.pathObject.api.plugin.customFormatValidators
}), parameter.getSchema(), value);
if (result.errors.length > 0) {
@ -422,23 +433,43 @@ function ParameterValue (parameter, raw) {
*
* **Note:** Do not use directly.
*
* @param {Operation} operation - The Swagger Operation object
* **Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
* object.
*
* @param {Operation|Path} opOrPath - The Operation or Path object
* @param {string} ptr - The JSON Pointer to the parameter
* @param {object} definition - The parameter definition
* @param {object} schema - The JSON Schema for the parameter
*
* @property {object} definition - The parameter definition
* @property {Operation} operationObject - The Operation object (Can be undefined for path-level parameters)
* @property {Path} pathObject - The Path object
* @property {string} ptr - The JSON Pointer to the parameter definition
* @property {object} schema - The JSON Schema for the parameter
*
* @constructor
*/
function Parameter (operation, ptr, definition, schema) {
this.operation = operation;
this.ptr = ptr;
this.definition = definition;
function Parameter (opOrPath, ptr, definition, schema) {
this.computedSchema = schema;
this.definition = definition;
this.ptr = ptr;
if (opOrPath instanceof Operation) {
this.operationObject = opOrPath;
this.pathObject = opOrPath.pathObject;
} else {
this.operationObject = undefined;
this.pathObject = opOrPath;
}
// Assign Swagger definition properties to the parameter for easy access
_.assign(this, definition);
debug('Found operation parameter (%s %s) at %s', operation.method.toUpperCase(), operation.path, ptr);
debug('Found %s parameter (%s in %s) at %s',
_.isUndefined(this.operationObject) ? 'path-level' : 'operation',
definition.name,
definition.in,
ptr);
}
/**
@ -456,7 +487,7 @@ Parameter.prototype.getSchema = function () {
* @returns {*} The sample value
*/
Parameter.prototype.getSample = function () {
return this.operation.api.plugin.getSample(this.computedSchema);
return this.pathObject.api.plugin.getSample(this.computedSchema);
};
/**
@ -528,10 +559,10 @@ Parameter.prototype.getValue = function (req) {
}
// Since we get the raw path parameter value, we need to URI decode it
pathMatch = this.operation.regexp.exec(parseUrl(decodeURIComponent(req.url)).pathname);
pathMatch = this.pathObject.regexp.exec(parseUrl(decodeURIComponent(req.url)).pathname);
if (pathMatch) {
value = pathMatch[_.findIndex(this.operation.regexp.keys, function (key) {
value = pathMatch[_.findIndex(this.pathObject.regexp.keys, function (key) {
return key.name === that.name;
}) + 1];
}
@ -549,6 +580,91 @@ Parameter.prototype.getValue = function (req) {
return new ParameterValue(this, value);
};
/**
* The Path object.
*
* **Note:** Do not use directly.
*
* **Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
* object.
*
* @param {SwaggerApi} api - The Swagger API object
* @param {string} path - The path string
* @param {ptr} ptr - The JSON Pointer to the path
* @param {object} definition - The path definition
* @param {regexp} regexp - The regexp used to match request paths against this path
*
* @property {SwaggerApi} api - The Swagger API object
* @property {object} definition - The path definition
* @property {Operation[]} operationObjects - The operation objects
* @property {Parameter[]} parameterObjects - The path-level parameter objects
* @property {string} path - The path string
* @property {ptr} ptr - The JSON Pointer to the path
* @property {regexp} regexp - The regexp used to match request paths against this path
*
* @constructor
*/
function Path (api, path, ptr, definition, regexp) {
this.api = api;
this.path = path;
this.ptr = ptr;
this.definition = definition;
this.regexp = regexp;
// Assign Swagger definition properties to the operation for easy access
_.assign(this, definition);
debug('Found path at %s', ptr);
this.parameterObjects = api.plugin.getPathParameters(this);
this.operationObjects = api.plugin.getOperations(this);
}
/**
* Return the operation for this path and method.
*
* @param {string} method - The method
*
* @returns {Operation[]} The Operation objects for this path and method or undefined if there is no operation for the
* provided method.
*/
Path.prototype.getOperation = function (method) {
return _.find(this.operationObjects, function (operationObject) {
return operationObject.method === method;
});
};
/**
* Return the operations for this path.
*
* @returns {Operation[]} The Operation objects for this path.
*/
Path.prototype.getOperations = function () {
return this.operationObjects;
};
/**
* Return the operations for this path and tag.
*
* @param {string} tag - The tag
*
* @returns {Operation[]} The Operation objects for this path and tag
*/
Path.prototype.getOperationsByTag = function (tag) {
return _.filter(this.operationObjects, function (operationObject) {
return _.contains(operationObject.tags, tag);
});
};
/**
* Return the parameters for this path.
*
* @returns {Parameter[]} The Parameter objects for this path.
*/
Path.prototype.getParameters = function () {
return this.parameterObjects;
};
/**
* Callback used for validation.
*
@ -572,6 +688,9 @@ Parameter.prototype.getValue = function (req) {
*
* **Note:** Do not use directly.
*
* **Extra Properties:** Other than the documented properties, this object also exposes all properties of the definition
* object.
*
* @param {object} plugin - The Swagger version plugin
* @param {object} definition - The Swagger definition
* @param {object} resolved - The fully resolved Swagger definition
@ -579,6 +698,17 @@ Parameter.prototype.getValue = function (req) {
* @param {object} options - The options passed to swaggerApi.create
* @param {validatorCallback[]} [options.customValidators] - The custom validators
*
* @property {function[]} customValidators - The array of custom validators
* @property {object} definition - The API definition
* @property {string} documentation - The URL to the Swagger documentation
* @property {object[]} errors - The validation errors or undefined if validation has not run
* @property {Path[]} pathObjects - The unique path objects
* @property {object} options - The options passed to the constructor
* @property {object} references - The reference metadata
* @property {object} resolved - The fully resolved API definition
* @property {string} version - The Swagger API version
* @property {object[]} warnings - The validation warnings or undefined if validation has not run
*
* @constructor
*/
function SwaggerApi (plugin, definition, resolved, references, options) {
@ -586,19 +716,19 @@ function SwaggerApi (plugin, definition, resolved, references, options) {
this.definition = definition;
this.documentation = plugin.documentation;
this.errors = undefined;
this.options = options;
this.plugin = plugin;
this.references = references;
this.resolved = resolved;
this.version = plugin.version;
this.warnings = undefined;
this.options = options;
// Assign Swagger definition properties to the api for easy access
_.assign(this, definition);
debug('New Swagger API (%s)', _.isString(options.definition) ? options.definition : 'JavaScript Object');
this.operationObjects = plugin.getOperations(this);
this.pathObjects = plugin.getPaths(this);
// Register custom validators
_.forEach(options.validators, this.registerValidator);
@ -640,24 +770,22 @@ SwaggerApi.prototype.getLastWarnings = function () {
* path and method combination.
*/
SwaggerApi.prototype.getOperation = function (pathOrReq, method) {
var predicate;
var url;
var pathObject = this.getPath(pathOrReq);
var operation;
if (_.isObject(pathOrReq)) {
method = pathOrReq.method;
url = parseUrl(pathOrReq.url).pathname;
predicate = function (operation) {
return operation.method === method && _.isArray(operation.regexp.exec(url));
};
} else {
predicate = function (operation) {
return operation.path === pathOrReq && operation.method === method;
};
if (!_.isUndefined(pathObject)) {
if (_.isObject(pathOrReq)) {
method = pathOrReq.method;
}
if (!_.isUndefined(method)) {
method = method.toLowerCase();
}
operation = pathObject.getOperation(method);
}
method = method.toLowerCase();
return _.find(this.operationObjects, predicate);
return operation;
};
/**
@ -668,9 +796,22 @@ SwaggerApi.prototype.getOperation = function (pathOrReq, method) {
* @returns {Operation[]} All operations for the provided path or all API operations.
*/
SwaggerApi.prototype.getOperations = function (path) {
return _.filter(this.operationObjects, function (operation) {
return _.isUndefined(path) ? true : operation.path === path;
});
var operations = [];
var pathObject;
if (_.isUndefined(path)) {
_.each(this.pathObjects, function (pObject) {
operations.push.apply(operations, pObject.getOperations());
});
} else {
pathObject = this.getPath(path);
if (!_.isUndefined(pathObject)) {
operations = pathObject.getOperations();
}
}
return operations;
};
/**
@ -681,9 +822,50 @@ SwaggerApi.prototype.getOperations = function (path) {
* @returns {Operation[]} All operations for the provided tag.
*/
SwaggerApi.prototype.getOperationsByTag = function (tag) {
return _.filter(this.operationObjects, function (operation) {
return _.contains(operation.tags, tag);
});
return _.reduce(this.pathObjects, function (operations, pathObject) {
operations.push.apply(operations, pathObject.getOperationsByTag(tag));
return operations;
}, []);
};
/**
* Returns the path object for the given path or request.
*
* **Note:** Below is the list of `reqOrPath` properties used when `reqOrPath` is an `http.ClientRequest`
* *(or equivalent)*:
*
* * `url`
*
* *(See: {@link https://nodejs.org/api/http.html#http_class_http_clientrequest})*
*
* @param {string|object} pathOrReq - The Swagger path string or the http client request *(or equivalent)*
*
* @returns {Path} The corresponding Path object for the requested path or request.
*/
SwaggerApi.prototype.getPath = function (pathOrReq) {
var url;
if (_.isObject(pathOrReq)) {
url = parseUrl(pathOrReq.url).pathname;
return _.find(this.pathObjects, function (pathObject) {
return _.isArray(pathObject.regexp.exec(url));
});
} else {
return _.find(this.pathObjects, function (pathObject) {
return pathOrReq === pathObject.path;
});
}
};
/**
* Returns all path objects for the Swagger API.
*
* @returns {Path[]} The Path objects
*/
SwaggerApi.prototype.getPaths = function () {
return this.pathObjects;
};
/**
@ -745,5 +927,6 @@ SwaggerApi.prototype.validate = function () {
module.exports = {
Operation: Operation,
Parameter: Parameter,
Path: Path,
SwaggerApi: SwaggerApi
};

Просмотреть файл

@ -94,14 +94,119 @@ module.exports.getJSONSchemaValidator = function () {
};
/**
* Creates an array of Operation objects for each operation defined in the Swagger document
* Creates an array of Operation objects for each operation defined in path definition.
*
* @param {types.SwaggerApi} api - The Swagger API object
* @param {types.Path} pathObject - The Path object
*
* @returns {types.Operation[]} The Operation object array
*/
module.exports.getOperations = function (api) {
module.exports.getOperations = function (pathObject) {
var operations = [];
var pPath = JsonRefs.pathFromPointer(pathObject.ptr);
var pParams = _.reduce(pathObject.definition.parameters, function (parameters, paramDef, index) {
parameters[paramDef.name + ':' + paramDef.in] = {
path: pPath.concat(['parameters', index.toString()]),
definition: paramDef
};
return parameters;
}, {});
_.forEach(pathObject.definition, function (operation, method) {
// Do not process non-operations
if (_.indexOf(vHelpers.supportedHttpMethods, method) === -1) {
return;
}
var cOperation = _.cloneDeep(operation); // Clone so we do not alter the input
var oParams = {}; // Used to keep track of unique parameters
var oPath = pPath.concat(method);
// Add path parameters
_.forEach(pParams, function (pParam, key) {
oParams[key] = pParam;
});
// Add operation parameters (Overrides path-level parameters of same name+in combination)
_.forEach(operation.parameters, function (paramDef, index) {
oParams[paramDef.name + ':' + paramDef.in] = {
path: oPath.concat(['parameters', index.toString()]),
definition: paramDef
};
});
// Attach our computed parameters/security to the operation
cOperation.parameters = _.map(_.values(oParams), function (parameter) {
// Used later by getOperationParameters to circumvent the chicken/egg situation (Removed there as well)
parameter.definition.$$$ptr$$$ = JsonRefs.pathToPointer(parameter.path);
return parameter.definition;
});
if (_.isUndefined(cOperation.security)) {
cOperation.security = pathObject.api.resolved.security;
}
operations.push(new types.Operation(pathObject.api, pathObject, method, JsonRefs.pathToPointer(oPath), cOperation));
});
return operations;
};
/**
* Returns an array of Parameter objects for the provided Operation.
*
* @param {types.Operation} operation - The Operation object
*
* @returns {types.Parameter[]} The Parameter object array
*/
module.exports.getOperationParameters = function (operation) {
var pParams = _.reduce(operation.pathObject.getParameters(), function (params, param) {
params[param.ptr] = param;
return params;
}, {});
return _.map(operation.parameters, function (paramDef) {
var ptr = paramDef.$$$ptr$$$;
var pParam = pParams[ptr];
// Remove so we do not have these properties litered throughout the document
delete paramDef.$$$ptr$$$;
if (_.isUndefined(pParam)) {
return new types.Parameter(operation, ptr, paramDef, vHelpers.getParameterSchema(paramDef));
} else {
return pParam;
}
});
};
/**
* Returns an array of path-level Parameter objects for the provided Path.
*
* @param {types.Path} path - The Path object
*
* @returns {types.Parameter[]} The Parameter object array
*/
module.exports.getPathParameters = function (path) {
return _.map(path.definition.parameters, function (paramDef, index) {
return new types.Parameter(path,
JsonRefs.pathToPointer(JsonRefs.pathFromPointer(path.ptr).concat(index.toString())),
paramDef,
vHelpers.getParameterSchema(paramDef));
});
};
/**
* Creates an array of Path objects for each path defined in the Swagger document.
*
* @param {types.SwaggerApi} api - The Swagger API object
*
* @returns {types.Path[]} The Operation object array
*/
module.exports.getPaths = function (api) {
var basePathPrefix = api.resolved.basePath || '/';
// Remove trailing slash from the basePathPrefix so we do not end up with double slashes
@ -109,76 +214,13 @@ module.exports.getOperations = function (api) {
basePathPrefix = basePathPrefix.substring(0, basePathPrefix.length - 1);
}
_.forEach(api.resolved.paths, function (pathDef, path) {
var pPath = ['paths', path];
var pParams = _.reduce(pathDef.parameters || [], function (parameters, paramDef, index) {
parameters[paramDef.name + ':' + paramDef.in] = {
path: pPath.concat(['parameters', index.toString()]),
definition: paramDef
};
return _.map(api.resolved.paths, function (pathDef, path) {
return new types.Path(api,
path,
JsonRefs.pathToPointer(['paths', path]),
pathDef,
pathToRegexp(basePathPrefix + path.replace(/\{/g, ':').replace(/\}/g, '')));
return parameters;
}, {});
var pRegexp = pathToRegexp(basePathPrefix + path.replace(/\{/g, ':').replace(/\}/g, ''));
_.forEach(pathDef, function (operation, method) {
// Do not process non-operations
if (_.indexOf(vHelpers.supportedHttpMethods, method) === -1) {
return;
}
var cOperation = _.cloneDeep(operation); // Clone so we do not alter the input
var oParams = {}; // Used to keep track of unique parameters
var oPath = pPath.concat(method);
// Add path parameters
_.forEach(pParams, function (pParam, key) {
oParams[key] = pParam;
});
// Add operation parameters (Overrides path-level parameters of same name+in combination)
_.forEach(operation.parameters, function (paramDef, index) {
oParams[paramDef.name + ':' + paramDef.in] = {
path: oPath.concat(['parameters', index.toString()]),
definition: paramDef
};
});
// Attach our computed parameters/security to the operation
cOperation.parameters = _.map(_.values(oParams), function (parameter) {
// Used later by getOperationParameters to circumvent the chicken/egg situation (Removed there as well)
parameter.definition.$$$ptr$$$ = JsonRefs.pathToPointer(parameter.path);
return parameter.definition;
});
if (_.isUndefined(cOperation.security)) {
cOperation.security = api.resolved.security;
}
operations.push(new types.Operation(api, path, method, JsonRefs.pathToPointer(oPath), cOperation, pRegexp));
});
});
return operations;
};
/**
* Returns an array of Parameter objects for the proviced Operation.
*
* @param {types.Operation} operation - The Operation object
*
* @returns {types.Parameter[]} The Parameter object array
*/
module.exports.getOperationParameters = function (operation) {
return _.map(operation.parameters, function (paramDef) {
var ptr = paramDef.$$$ptr$$$;
// Remove so we do not have these properties litered throughout the document
delete paramDef.$$$ptr$$$;
return new types.Parameter(operation, ptr, paramDef, vHelpers.getParameterSchema(paramDef));
});
};

Просмотреть файл

@ -31,7 +31,6 @@ var assert = require('assert');
var JsonRefs = require('json-refs');
var swaggerApi = typeof window === 'undefined' ? require('..') : window.SwaggerApi;
var pathLoader = require('path-loader');
var types = require('../lib/types');
var YAML = require('js-yaml');
var helpers = require('../lib/helpers');
@ -123,8 +122,8 @@ describe('sway (Swagger 2.0)', function () {
});
// Validate the operations (Simple tests for now, deeper testing is below)
assert.ok(_.isArray(theApi.operationObjects));
assert.ok(theApi.operationObjects.length > 0);
assert.ok(_.isArray(theApi.pathObjects));
assert.ok(theApi.pathObjects.length > 0);
};
}
@ -387,7 +386,7 @@ describe('sway (Swagger 2.0)', function () {
var pathDef = swagger.resolved.paths[path];
var operationDef = swagger.resolved.paths[path][method];
assert.equal(operation.path, path);
assert.equal(operation.pathObject.path, path);
assert.equal(operation.method, method);
assert.equal(operation.ptr, '#/paths/~1pet~1{petId}/' + method);
@ -421,7 +420,7 @@ describe('sway (Swagger 2.0)', function () {
var operation = swagger.getOperation(path, method);
var pathDef = swagger.resolved.paths[path];
assert.equal(operation.path, path);
assert.equal(operation.pathObject.path, path);
assert.equal(operation.method, method);
assert.equal(operation.ptr, '#/paths/~1pet~1{petId}~1uploadImage/post');
@ -470,19 +469,19 @@ describe('sway (Swagger 2.0)', function () {
var updatePet = api.getOperation('/pet/{petId}', 'post');
// Make sure they are of the proper type
assert.ok(createPet.regexp instanceof RegExp);
assert.ok(updatePet.regexp instanceof RegExp);
assert.ok(createPet.pathObject.regexp instanceof RegExp);
assert.ok(updatePet.pathObject.regexp instanceof RegExp);
// Make sure they have the proper keys
assert.equal(0, createPet.regexp.keys.length);
assert.equal(1, updatePet.regexp.keys.length);
assert.equal('petId', updatePet.regexp.keys[0].name);
assert.equal(0, createPet.pathObject.regexp.keys.length);
assert.equal(1, updatePet.pathObject.regexp.keys.length);
assert.equal('petId', updatePet.pathObject.regexp.keys[0].name);
// Make sure they match the expected URLs
assert.ok(_.isArray(createPet.regexp.exec(basePath + '/pet')));
assert.ok(!_.isArray(createPet.regexp.exec(basePath + '/pets')));
assert.ok(_.isArray(updatePet.regexp.exec(basePath + '/pet/1')));
assert.ok(!_.isArray(createPet.regexp.exec(basePath + '/pets/1')));
assert.ok(_.isArray(createPet.pathObject.regexp.exec(basePath + '/pet')));
assert.ok(!_.isArray(createPet.pathObject.regexp.exec(basePath + '/pets')));
assert.ok(_.isArray(updatePet.pathObject.regexp.exec(basePath + '/pet/1')));
assert.ok(!_.isArray(createPet.pathObject.regexp.exec(basePath + '/pets/1')));
}
it('should create proper regexp (with basePath)', function () {
@ -1901,6 +1900,80 @@ describe('sway (Swagger 2.0)', function () {
});
});
describe('Path', function () {
it('should have proper structure', function () {
var path = '/pet/{petId}';
var pathObject = swagger.getOperation(path, 'get').pathObject;
assert.deepEqual(pathObject.api, swagger);
assert.equal(pathObject.path, path);
assert.equal(pathObject.ptr, JsonRefs.pathToPointer(['paths', path]));
assert.deepEqual(pathObject.definition, swagger.resolved.paths[path]);
// Make sure they are of the proper type
assert.ok(pathObject.regexp instanceof RegExp);
// Make sure they have the proper keys
assert.equal(1, pathObject.regexp.keys.length);
assert.equal('petId', pathObject.regexp.keys[0].name);
// Make sure they match the expected URLs
assert.ok(_.isArray(pathObject.regexp.exec(swagger.resolved.basePath + '/pet/1')));
assert.ok(!_.isArray(pathObject.regexp.exec(swagger.resolved.basePath + '/pets/1')));
});
describe('#getOperation', function () {
it('should return the expected operation', function () {
assert.ok(!_.isUndefined(swagger.getPath('/pet/{petId}').getOperation('get')));
});
it('should return no operation for the missing method', function () {
assert.ok(_.isUndefined(swagger.getPath('/pet/{petId}').getOperation('head')));
});
});
describe('#getOperations', function () {
it('should return the expected operations', function () {
assert.equal(swagger.getPath('/pet/{petId}').getOperations().length, 3);
});
it('should return no operations', function (done) {
var cSwagger = _.cloneDeep(swaggerDoc);
var path = '/petz';
cSwagger.paths[path] = {};
swaggerApi.create({
definition: cSwagger
}).then(function (api) {
assert.equal(api.getPath(path).getOperations().length, 0);
}).then(done, done);
});
});
describe('#getOperationsByTag', function () {
it('should return the expected operations', function () {
assert.equal(swagger.getPath('/pet/{petId}').getOperationsByTag('pet').length, 3);
});
it('should return no operations', function () {
assert.equal(swagger.getPath('/pet/{petId}').getOperationsByTag('petz').length, 0);
});
});
describe('#getParameters', function () {
it('should return the expected parameters', function () {
var parameters = swagger.getPath('/pet/{petId}').getParameters();
assert.equal(parameters.length, 1);
});
it('should return no parameters', function () {
assert.equal(swagger.getPath('/pet').getParameters().length, 0);
});
});
});
describe('SwaggerApi', function () {
beforeEach(function () {
swagger.customValidators = [];
@ -1991,6 +2064,38 @@ describe('sway (Swagger 2.0)', function () {
});
});
describe('#getPath', function () {
describe('path', function () {
it('should return the expected path object', function () {
assert.ok(!_.isUndefined(swagger.getPath('/pet/{petId}')));
});
it('should return no path object', function () {
assert.ok(_.isUndefined(swagger.getPath('/petz/{petId}')));
});
});
describe('http.ClientRequest (or similar)', function () {
it('should return the expected path object', function () {
assert.ok(!_.isUndefined(swagger.getPath({
url: swagger.basePath + '/pet/1'
})));
});
it('should return no path object', function () {
assert.ok(_.isUndefined(swagger.getPath({
url: swagger.basePath + '/petz/1'
})));
});
});
});
describe('#getPaths', function () {
it('should return the expected path objects', function () {
assert.equal(swagger.getPaths().length, Object.keys(swagger.resolved.paths).length);
});
});
describe('#registerValidator', function () {
it('should throw TypeError for invalid arguments', function () {
var scenarios = [