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

hapi-swagger

Package Overview
Dependencies
Maintainers
1
Versions
163
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hapi-swagger - npm Package Compare versions

Comparing version 3.0.1 to 3.1.0

test/dereference-test.js

3

bin/test-server.js

@@ -73,3 +73,4 @@ 'use strict';

}
}]
}],
derefJSONSchema: false
};

@@ -76,0 +77,0 @@

'use strict';
const Hoek = require('hoek');
const Joi = require('joi');
const JSONDeRef = require('json-schema-ref-parser');
const Filter = require('../lib/filter');

@@ -60,3 +61,3 @@ const Group = require('../lib/group');

*/
builder.getSwaggerJSON = function (settings, request) {
builder.getSwaggerJSON = function (settings, request, callback) {

@@ -80,3 +81,3 @@ // remove items that cannot be changed by user

routes = Filter.byTags(['api'], routes);
Sort.byPathMethod(['api'], routes);
Sort.paths(settings.sortPath, routes);

@@ -96,3 +97,9 @@ // filter routes displayed based on tags passed in query string

return internals.removeNoneSchemaOptions(out);
out = internals.removeNoneSchemaOptions(out);
if (settings.derefJSONSchema === true) {
builder.dereference(out, callback);
} else {
callback(null, out);
}
};

@@ -102,2 +109,22 @@

/**
* dereference a schema
*
* @param {Object} schema
* @param {Object} callback
*/
builder.dereference = function (schema, callback) {
JSONDeRef.dereference(schema, function (err, json) {
if (!err) {
delete json.definitions;
} else {
err = { 'error': 'fail to dereference schema' };
}
callback(err, json);
});
};
/**
* finds the current host

@@ -145,3 +172,5 @@ *

'lang',
'addXProperties'
'sortPaths',
'addXProperties',
'derefJSONSchema'
].forEach( (element) => {

@@ -148,0 +177,0 @@

'use strict';
const Hoek = require('hoek');
const ShortId = require('shortid');
const Properties = require('../lib/properties');

@@ -21,32 +22,18 @@ const Utilities = require('../lib/utilities');

// covert JOI object into internal object
let newDefinition;
if (Array.isArray(joiObj)){
let propertyObj = Properties.parseProperties(joiObj, definitionCollection);
let propertyArray = Properties.swaggerObjectToArray(propertyObj, null);
newDefinition = internals.wrap(propertyArray);
let parameterArray = Properties.toParameters(joiObj, definitionCollection);
newDefinition = internals.wrapParameters(parameterArray);
} else {
newDefinition = Properties.parseProperty(definitionName, joiObj, definitionCollection);
newDefinition = Properties.parseProperty(definitionName || altName, joiObj, definitionCollection);
}
return definitions.append(definitionName, newDefinition, definitionCollection, altName);
};
/**
* append a new definition object
*
* @param {string} definitionName
* @param {Object} definition
* @param {Object} definitionCollection
* @param {string} altName
* @return {Object}
*/
definitions.append = function (definitionName, definition, definitionCollection, altName) {
const formatted = internals.createProperties( definition.properties );
definition.properties = formatted.properties;
if (formatted.required){
definition.required = formatted.required;
// format structure into new definition object
const formatted = internals.formatProperties( newDefinition.properties );
if (formatted.properties){
newDefinition.properties = formatted.properties;
}
return internals.appendFormatted(definitionName, definition, definitionCollection, altName);
return internals.appendFormatted(definitionName, newDefinition, definitionCollection, altName);
};

@@ -71,2 +58,4 @@

//definitionName = definitionName + Math.random() * (99999 - 0) + 0;
// find existing definition by this definitionName

@@ -82,3 +71,8 @@ const foundDefinition = definitionCollection[definitionName];

// to stop reuse of definition with same name but different structures
definitionCollection[altName] = definition;
if (!altName) {
altName = ShortId.generate();
}
//definition.name = altName + 'x';
definitionCollection[altName] = internals.formatProperty( definition );
out = altName;

@@ -88,2 +82,3 @@ }

// create new definition
//definition.name = (definitionName || altName) + 'x';
definitionCollection[definitionName || altName] = definition;

@@ -98,3 +93,3 @@ out = definitionName || altName;

/**
* builds definition object properties structure (input is swagger parameter model)
* builds definition object properties structure from parameters
*

@@ -104,3 +99,3 @@ * @param {Object} parameters

*/
internals.createProperties = function (parameters) {
internals.formatProperties = function (parameters) {

@@ -111,3 +106,2 @@ let out = {

for (let key in parameters) {

@@ -121,24 +115,39 @@ let obj = parameters[key];

}
out.required.push(obj.name || key);
out.required.push(obj.name);
}
// remove emtpy properties
obj = Utilities.deleteEmptyProperties(obj);
out.properties[obj.name || key] = obj;
obj = internals.formatProperty(obj);
}
return Utilities.deleteEmptyProperties(out);
};
// recurse into child objects
if (obj.type === 'object' && obj.properties) {
out.properties[obj.name] = internals.createProperties(obj.properties);
} else {
// if child has no name use its key
out.properties[obj.name || key] = obj;
}
// remove unneeded properties
delete obj.name;
delete obj.required;
/**
* formats a parameter for use in a definition object
*
* @param {Object} parameter
* @return {Object}
*/
internals.formatProperty = function (obj) {
// add $ref directly to parent and delete schema
if (obj.schema) {
obj.$ref = obj.schema.$ref;
delete obj.schema;
}
return out;
// remove emtpy properties
obj = Utilities.deleteEmptyProperties(obj);
// remove unneeded properties
delete obj.name;
delete obj.required;
return obj;
};
/**

@@ -150,3 +159,3 @@ * wraps definition object in the JSON schema structure

*/
internals.wrap = function (parameters) {
internals.wrapParameters = function (parameters) {

@@ -157,3 +166,3 @@ let out = {

},
props = internals.createProperties(parameters);
props = internals.formatProperties(parameters);

@@ -160,0 +169,0 @@ // merge in properties and required structures

@@ -23,3 +23,5 @@ 'use strict';

lang: Joi.string().valid(['en', 'es', 'pt', 'ru']),
addXProperties: Joi.boolean()
sortPaths: Joi.string().valid(['unsorted', 'path-method']),
addXProperties: Joi.boolean(),
derefJSONSchema: Joi.boolean()
}).unknown();

@@ -40,3 +42,5 @@

'lang': 'en',
'addXProperties': false
'sortPaths': 'unsorted',
'addXProperties': false,
'derefJSONSchema': false
};

@@ -57,20 +61,2 @@

// There is no way to cover this differs from Hapi 9 to 10+
/* $lab:coverage:off$ */
if (plugin.registrations){
Hoek.assert(plugin.registrations.vision, 'Missing vision plug-in registation');
Hoek.assert(plugin.registrations.inert, 'Missing inert plug-in registation');
}
/* $lab:coverage:on$ */
// add routing for swaggerui static assets /swaggerui/
plugin.views({
engines: {
html: {
module: require('handlebars')
}
},
path: swaggerDirPath
});
// add routing swagger json

@@ -80,3 +66,3 @@ plugin.route([{

path: settings.jsonPath,
config: {
config: {
auth: settings.auth,

@@ -86,3 +72,6 @@ handler: (request, reply) => {

Joi.assert(settings, schema);
reply(builder.getSwaggerJSON(settings, request));
builder.getSwaggerJSON(settings, request, function (err, json) {
reply(json).type('application/json');
});
},

@@ -98,2 +87,21 @@ plugins: {

if (settings.enableDocumentation === true) {
// There is no way to cover this differs from Hapi 9 to 10+
/* $lab:coverage:off$ */
if (plugin.registrations){
Hoek.assert(plugin.registrations.vision, 'Missing vision plug-in registation');
Hoek.assert(plugin.registrations.inert, 'Missing inert plug-in registation');
}
/* $lab:coverage:on$ */
// add routing for swaggerui static assets /swaggerui/
plugin.views({
engines: {
html: {
module: require('handlebars')
}
},
path: swaggerDirPath
});
plugin.route([{

@@ -109,3 +117,3 @@ method: 'GET',

}
}, {
},{
method: 'GET',

@@ -112,0 +120,0 @@ path: settings.swaggerUIPath + '{path*}',

@@ -48,2 +48,4 @@ 'use strict';

Responses.build({},{},{},{});
let routesData = [];

@@ -172,3 +174,3 @@

swagger.definitions,
out.operationId + '_payload'
'parameters_' + out.operationId + '_' + method.toLowerCase()
)

@@ -181,9 +183,9 @@ };

} else {
payloadParameters = Properties.joiToSwaggerParameters( internals.getJOIObj(route, 'payloadParams'), 'formData', swagger.definitions );
payloadParameters = Properties.toParameters( internals.getJOIObj(route, 'payloadParams'), swagger.definitions, 'formData' );
}
out.parameters = out.parameters.concat(
Properties.joiToSwaggerParameters( internals.getJOIObj(route, 'headerParams'), 'header', swagger.definitions ),
Properties.joiToSwaggerParameters( internals.getJOIObj(route, 'pathParams'), 'path', swagger.definitions ),
Properties.joiToSwaggerParameters( internals.getJOIObj(route, 'queryParams'), 'query', swagger.definitions )
Properties.toParameters( internals.getJOIObj(route, 'headerParams'), swagger.definitions, 'header' ),
Properties.toParameters( internals.getJOIObj(route, 'pathParams'), swagger.definitions, 'path' ),
Properties.toParameters( internals.getJOIObj(route, 'queryParams'), swagger.definitions, 'query' )
);

@@ -194,3 +196,10 @@ if (payloadParameters){

out.responses = Responses.build( route.responses, route.responseSchema, route.responseStatus, swagger.definitions, out.operationId );
//let name = out.operationId + method;
out.responses = Responses.build(
route.responses,
route.responseSchema,
route.responseStatus,
swagger.definitions,
out.operationId + '_' + method.toLowerCase()
);

@@ -197,0 +206,0 @@ if (!pathObj[path]){

@@ -29,19 +29,7 @@ 'use strict';

/**
* builds a swagger definition object from a JOI object
*
* @param {Object} joiObjs
* @param {Array} definitionCollection
* @return {Object}
*/
properties.joiToSwaggerDefinition = function (joiObjs, definitionCollection) {
return properties.parseProperties(joiObjs, definitionCollection);
};
/**
* builds a swagger parameters object from a JOI object
*
* @param {Object} joiObjs
* @param {Object} joiObj
* @param {String} type

@@ -51,24 +39,12 @@ * @param {Array} definitionCollection

*/
properties.joiToSwaggerParameters = function (joiObjs, type, definitionCollection) {
properties.toParameters = function (joiObj, definitionCollection, type) {
const propertyObj = properties.parseProperties(joiObjs, definitionCollection, type);
return properties.swaggerObjectToArray(propertyObj, type);
};
/**
* converts an object to an array of properties
*
* @param {Object} obj
* @param {String} type
* @return {Array}
*/
properties.swaggerObjectToArray = function (obj, type) {
const propertyObj = properties.parseProperties(joiObj, definitionCollection, type);
const keys = Object.keys(propertyObj);
let out = [];
const keys = Object.keys(obj);
// object to array
keys.forEach( (element, index) => {
let key = keys[index];
let item = obj[key];
let item = propertyObj[key];
item.name = key;

@@ -85,22 +61,4 @@ if (type) {

/**
* turns JOI object into an array
* needed to covert custom parameters objects passed in by plug-in route options
*
* @param {Object} obj
* @return {Array}
*/
properties.joiObjectToArray = function (obj) {
let out = [];
for (let key in obj) {
out.push({
key: key,
schema: obj[key]
});
}
return out;
};
/**

@@ -111,2 +69,3 @@ * parse Joi validators object into an object of swagger properties

* @param {Array} definitionCollection
* @param {String} type
* @return {Object}

@@ -145,2 +104,21 @@ */

/**
* turns JOI object into an array
* needed to covert custom parameters objects passed in by plug-in route options
*
* @param {Object} obj
* @return {Array}
*/
properties.joiObjectToArray = function (obj) {
let out = [];
for (let key in obj) {
out.push({
key: key,
schema: obj[key]
});
}
return out;
};
/**
* parse Joi validators object into a swagger property

@@ -174,14 +152,4 @@ *

// add common properties
property.description = Hoek.reach(joiObj, '_description');
property.notes = Hoek.reach(joiObj, '_notes');
property.tags = Hoek.reach(joiObj, '_tags');
property.example = Hoek.reach(joiObj, '_examples.0');
property = properties.parsePropertyMetadata(property, joiObj);
// add reqired state only if true
if (Hoek.reach(joiObj, '_flags.presence')) {
property.required = (Hoek.reach(joiObj, '_flags.presence') === 'required') ? true : undefined;
}
property.default = Hoek.reach(joiObj, '_flags.default');
// add enum

@@ -225,2 +193,26 @@ let describe = joiObj.describe();

/**
* parse property metadata
*
* @param {Object} property
* @param {Object} joiObj
* @return {Object}
*/
properties.parsePropertyMetadata = function (property, joiObj) {
// add common properties
property.description = Hoek.reach(joiObj, '_description');
property.notes = Hoek.reach(joiObj, '_notes');
property.tags = Hoek.reach(joiObj, '_tags');
property.example = Hoek.reach(joiObj, '_examples.0');
// add reqired state only if true
if (Hoek.reach(joiObj, '_flags.presence')) {
property.required = (Hoek.reach(joiObj, '_flags.presence') === 'required') ? true : undefined;
}
property.default = Hoek.reach(joiObj, '_flags.default');
return property;
};
/**
* parse number property

@@ -255,6 +247,12 @@ *

const joiObjs = joiObj._inner.children;
joiObj = joiObj._inner.children;
property.name = name;
property.type = 'object';
property.properties = properties.parseProperties(joiObjs, definitionCollection);
if (name) {
property.schema = {
'$ref': '#/definitions/' + require('../lib/definitions').appendJoi(name, joiObj, definitionCollection)
};
} else {
property.properties = properties.parseProperties(joiObj, definitionCollection);
}
return property;

@@ -286,3 +284,3 @@ };

// set swaggers collectionFormat to one that works with hapi
if (type === 'query' || type === 'formData'){
if (type === 'query' || type === 'formData') {
property.collectionFormat = 'multi';

@@ -302,3 +300,3 @@ }

let arrayProperty = properties.parseProperty(name, firstInclusionType, definitionCollection);
if (internals.simpleTypePropertyMap[ firstInclusionType._type.toLowerCase() ]){
if (internals.simpleTypePropertyMap[firstInclusionType._type.toLowerCase()]) {
// map simple types directly

@@ -308,11 +306,7 @@ property.items = {

};
if ( arrayProperty.format ){
if (arrayProperty.format) {
property.items.format = arrayProperty.format;
}
} else {
// create definitions for complex types
// delay invocation of dependency until runtime to deal with circular dependencies with properties
property.items = {
'$ref': '#/definitions/' + require('../lib/definitions').append(name, arrayProperty, definitionCollection)
};
property.items = arrayProperty.schema;
}

@@ -319,0 +313,0 @@ }

@@ -5,2 +5,3 @@ 'use strict';

const Definitions = require('../lib/definitions');
const ShortId = require('shortid');
const Utilities = require('../lib/utilities');

@@ -15,3 +16,3 @@

*
* @param {Object} userDefindedObjs
* @param {Object} userDefindedSchemas
* @param {Object} defaultSchema

@@ -22,3 +23,3 @@ * @param {Object} statusSchemas

*/
responses.build = function (userDefindedObjs, defaultSchema, statusSchemas, definitionCollection, operationId) {
responses.build = function (userDefindedSchemas, defaultSchema, statusSchemas, definitionCollection, altName) {

@@ -28,3 +29,3 @@ let out = {};

// add defaultSchema to statusSchemas if needed
if (defaultSchema && (Hoek.reach(statusSchemas, '200') === undefined)) {
if (Utilities.hasProperties(defaultSchema) && (Hoek.reach(statusSchemas, '200') === undefined)) {
statusSchemas[200] = defaultSchema;

@@ -34,27 +35,34 @@ }

// loop for each status and convert schema into a definition
if (statusSchemas) {
if (Utilities.hasProperties(statusSchemas)){
for (let key in statusSchemas) {
if (statusSchemas.hasOwnProperty(key)) {
const responseName = Hoek.reach(statusSchemas[key], '_settings.language.label');
out[key] = {
description: Hoek.reach(statusSchemas[key], '_description')
};
out[key].headers = Utilities.getJoiMetaProperty(statusSchemas[key], 'headers');
out[key].example = Utilities.getJoiMetaProperty(statusSchemas[key], 'example');
let responseName;
// only add schema if object has children
if (Utilities.hasJoiChildren(statusSchemas[key])) {
out[key] = {
schema: {
'$ref': '#/definitions/' + Definitions.appendJoi(responseName, statusSchemas[key], definitionCollection, operationId + '_' + key)
}
};
// invert naming if on label is supplied
if (Hoek.reach(statusSchemas[key], '_settings.language.label')) {
responseName = Hoek.reach(statusSchemas[key], '_settings.language.label');
} else {
responseName = internals.altLabel(altName, key);
altName = ShortId.generate();
}
out[key] = {
'description': Hoek.reach(statusSchemas[key], '_description'),
'schema': {
'$ref': '#/definitions/' + Definitions.appendJoi(responseName, statusSchemas[key], definitionCollection, 'response_' + altName),
'title': internals.altLabel(altName, key)
}
out[key] = Utilities.deleteEmptyProperties(out[key]);
// make sure we always have a description as its required for swagger response object
if (!out[key].description){
out[key].description = HTTPStatus[key].replace('OK','Successful');
}
};
out[key].schema.title = responseName;
out[key].headers = Utilities.getJoiMetaProperty(statusSchemas[key], 'headers');
out[key].example = Utilities.getJoiMetaProperty(statusSchemas[key], 'example');
out[key] = Utilities.deleteEmptyProperties(out[key]);
// make sure we always have a description as its required for swagger response object
if (!out[key].description) {
out[key].description = HTTPStatus[key].replace('OK', 'Successful');
}
}

@@ -73,6 +81,6 @@ } else {

// use plug-in overrides to enchance hapi objects and properties
if (Utilities.hasProperties(userDefindedObjs)) {
out = internals.override(out, userDefindedObjs, definitionCollection, operationId);
// out = internals.override({}, userDefindedObjs, definitionCollection);
if (Utilities.hasProperties(userDefindedSchemas)) {
out = internals.override(out, userDefindedSchemas, definitionCollection, altName);
}
return Utilities.deleteEmptyProperties(out);

@@ -83,25 +91,30 @@ };

/**
* replaces discovered objects with user defined objects
* replaces discovered response objects with user defined objects
*
* @param {Object} discoveredObjs
* @param {Object} userDefindedObjs
* @param {Object} discoveredSchemas
* @param {Object} userDefindedSchemas
* @param {Object} definitionCollection
* @param {String} altName
* @return {Object}
*/
internals.override = function (discoveredObjs, userDefindedObjs, definitionCollection, operationId) {
internals.override = function (discoveredSchemas, userDefindedSchemas, definitionCollection, altName) {
for (let key in userDefindedObjs) {
if (userDefindedObjs.hasOwnProperty(key)) {
for (let key in userDefindedSchemas) {
if (userDefindedSchemas.hasOwnProperty(key)) {
// create a new object by cloning - dont modify user definded objects
let out = Hoek.clone(userDefindedObjs[key]);
let out = Hoek.clone(userDefindedSchemas[key]);
// test for any JOI objects
if (Hoek.reach(userDefindedObjs[key], 'schema.isJoi') && userDefindedObjs[key].schema.isJoi === true) {
//var responseName = Utilities.getJoiMetaProperty(userDefindedObjs[key].schema, 'name');
const responseName = Hoek.reach(userDefindedObjs[key].schema, '_settings.language.label');
if (Hoek.reach(userDefindedSchemas[key], 'schema.isJoi') && userDefindedSchemas[key].schema.isJoi === true) {
const responseName = Hoek.reach(userDefindedSchemas[key].schema, '_settings.language.label');
// convert JOI objects into Swagger defination references
out.schema = {
'$ref': '#/definitions/' + Definitions.appendJoi(responseName, userDefindedObjs[key].schema, definitionCollection, operationId + '_' + key)
'$ref': '#/definitions/' + Definitions.appendJoi(
responseName,
userDefindedSchemas[key].schema,
definitionCollection,
internals.altLabel(altName, key)
)
};

@@ -111,7 +124,19 @@ }

// overwrite discovery with user definded
discoveredObjs[key] = out;
discoveredSchemas[key] = Utilities.deleteEmptyProperties(out);
}
}
return discoveredObjs;
return discoveredSchemas;
};
/**
* create alt label for response object
*
* @param {String} altName
* @param {String} key
* @return {String}
*/
internals.altLabel = function (altName, key) {
return 'response_' + altName + '_' + key;
};

@@ -11,10 +11,14 @@ 'use strict';

*
* @param {String} sortType
* @param {Array} routes
* @return {Array}
*/
sort.byPathMethod = function (routes) {
sort.paths = function (sortType, routes) {
routes.sort(
Utilities.firstBy('path').thenBy('method')
);
if (sortType === 'path-method') {
routes.sort(
Utilities.firstBy('path').thenBy('method')
);
}
return routes;

@@ -21,0 +25,0 @@ };

@@ -56,2 +56,6 @@ 'use strict';

}
// delete object which does not have its own properties
if (utilities.isObject(obj[key]) && utilities.hasProperties(obj[key]) === false) {
delete obj[key];
}
}

@@ -58,0 +62,0 @@ }

{
"name": "hapi-swagger",
"description": "A swagger documentation UI generator plugin for hapi",
"version": "3.0.1",
"version": "3.1.0",
"author": "Glenn Jones",

@@ -28,2 +28,3 @@ "repository": {

"joi": "7.0.1",
"shortid": "2.2.4",
"json-schema-ref-parser": "^1.4.0"

@@ -37,3 +38,3 @@ },

"code": "2.0.1",
"hapi": "^11.1.1",
"hapi": "^12.0.0",
"wreck": "7.0.0",

@@ -51,4 +52,4 @@ "coveralls": "2.11.6",

"peerDependencies": {
"hapi": "^9.0.1 || ^10.0.0 || ^11.0.0"
"hapi": "^9.0.1 || ^10.0.0 || ^11.0.0 || ^12.0.0"
}
}
# hapi-swagger
This is a [Swagger UI](https://github.com/wordnik/swagger-ui) plug-in for [HAPI](http://hapijs.com/) v9.x to v11.x When installed it will self document HTTP API interface in a project.
This is a [The OpenAPI (aka Swagger)](https://openapis.org/) plug-in for [HAPI](http://hapijs.com/) v9.x to v12.x When installed it will self document the API interface
in a project.

@@ -20,3 +21,4 @@ [![build status](https://img.shields.io/travis/glennjones/hapi-swagger.svg?style=flat-square)](http://travis-ci.org/glennjones/hapi-swagger)

You will also need to install the `inert` and `vision` plugs-ins which support templates and static content serving.
If you want to view the documentation from your API you will also need to install the `inert` and `vision` plugs-ins which support templates and static
content serving. If you wish just to used swagger.json without the documentation for example with swagger-codegen simply set `enableDocumentation` to false

@@ -108,3 +110,4 @@ $ npm install inert --save

* `lang`: (string) The language of the UI either `en`, `es`, `pt` or `ru` - default: `en`
* `securityDefinitions:`: (array) Containing [Security Definitions Object](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securityDefinitionsObject). No defaults are provided.
* `tags`: (object) Containing [Tag Object] (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#tagObject) used to group endpoints in swagger-ui.
* `securityDefinitions:`: (array) Containing [Security Definitions Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#securityDefinitionsObject). No defaults are provided.

@@ -462,2 +465,2 @@ Defaults for routes settings (these can also be set a individual path level):

### Issues
If you find any issue please file here on github and I will try and fix them.
If you find any issue please file here on github and I will try and fix them.

@@ -53,20 +53,16 @@ 'use strict';

expect(response.statusCode).to.equal(200);
expect(response.result.paths['/foo/v1/bar'].post.parameters[0].schema).to.deep.equal({
'$ref': '#/definitions/foov1bar_payload'
'$ref': '#/definitions/parameters_foov1bar_post'
});
expect(response.result.definitions.foov1bar_payload).to.deep.equal({
expect(response.result.definitions.parameters_foov1bar_post).to.deep.equal({
'properties': {
'outer1': {
'properties': {
'inner1': {
'type': 'string'
}
}
'$ref': '#/definitions/outer1',
'type': 'object'
},
'outer2': {
'properties': {
'inner2': {
'type': 'string'
}
}
'$ref': '#/definitions/outer2',
'type': 'object'
}

@@ -76,2 +72,11 @@ },

});
expect(response.result.definitions.outer1).to.deep.equal({
'properties': {
'inner1': {
'type': 'string'
}
},
'type': 'object'
});
done();

@@ -78,0 +83,0 @@ });

@@ -83,5 +83,5 @@ 'use strict';

expect(response.result.paths['/test/'].post.parameters[0].schema).to.deep.equal({
'$ref': '#/definitions/test_payload'
'$ref': '#/definitions/parameters_test_post'
});
expect(response.result.definitions.test_payload).to.deep.equal(defination);
expect(response.result.definitions.parameters_test_post).to.deep.equal(defination);
done();

@@ -88,0 +88,0 @@ });

@@ -14,3 +14,28 @@ 'use strict';

// these are example are taken from https://github.com/hapijs/lout/blob/master/test/routes/default.js
// License: https://github.com/hapijs/lout/blob/master/LICENSE
/*
Copyright (c) 2012-2014, Walmart and other contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The names of any contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const routes = [{

@@ -17,0 +42,0 @@ method: 'GET',

@@ -340,2 +340,5 @@ 'use strict';

});

@@ -5,2 +5,3 @@ 'use strict';

const Lab = require('lab');
const Helper = require('../test/helper.js');
const Properties = require('../lib/properties.js');

@@ -13,2 +14,3 @@

lab.experiment('property - ', () => {

@@ -151,8 +153,14 @@

//console.log(JSON.stringify(Properties.parseProperty('x', Joi.object().keys({ 'text': Joi.string() }), {}, [], 'formData' )));
//console.log(JSON.stringify(Properties.parseProperty('x', Joi.object({ 'text': Joi.string() }), {}, [], 'formData' )));
/* Change from inline to definiation objects
expect(Properties.parseProperty('x', Joi.object({ 'text': Joi.string() }))).to.deep.equal({ 'type': 'object', 'name': 'x', 'properties': { 'text': { 'type': 'string' } } });
expect(Properties.parseProperty('x', Joi.object().keys({ 'text': Joi.string() }))).to.deep.equal({ 'type': 'object', 'name': 'x', 'properties': { 'text': { 'type': 'string' } } });
*/
expect(Properties.parseProperty('x', Joi.object({ 'text': Joi.string() }), {}, [], 'formData')).to.deep.equal({ 'type': 'object', 'name': 'x', 'schema': { '$ref': '#/definitions/x' } });
expect(Properties.parseProperty('x', Joi.object().keys({ 'text': Joi.string() }), {}, [], 'formData')).to.deep.equal({ 'type': 'object', 'name': 'x', 'schema': { '$ref': '#/definitions/x' } });
/* not yet 'x-',

@@ -182,121 +190,2 @@ {}

lab.test('parse deep structure with children', (done) => {
const deepStructure = Joi.object({
outer1: Joi.object({
inner1: Joi.string()
}),
outer2: Joi.object({
inner2: Joi.string()
})
}).description('body description').notes(['body notes']);
const deepStructureJSON = {
'type': 'object',
'description': 'body description',
'notes': [
'body notes'
],
'name': 'x',
'properties': {
'outer1': {
'type': 'object',
'name': 'outer1',
'properties': {
'inner1': {
'type': 'string'
}
}
},
'outer2': {
'type': 'object',
'name': 'outer2',
'properties': {
'inner2': {
'type': 'string'
}
}
}
}
};
expect(Properties.parseProperty('x', deepStructure)).to.deep.equal(deepStructureJSON);
done();
});
lab.test('parse deep structure with child description, notes, name etc', (done) => {
const deepStructure = Joi.object({
outer1: Joi.object({
inner1: Joi.string()
.description('child description')
.notes(['child notes'])
.tags(['child', 'api'])
.required()
}),
outer2: Joi.object({
inner2: Joi.number()
.description('child description')
.notes(['child notes'])
.tags(['child', 'api'])
.min(5)
.max(10)
.required()
})
});
const deepStructureJSON = {
'type': 'object',
'name': 'x',
'properties': {
'outer1': {
'type': 'object',
'name': 'outer1',
'properties': {
'inner1': {
'type': 'string',
'description': 'child description',
'notes': [
'child notes'
],
'tags': [
'child',
'api'
],
'required': true
}
}
},
'outer2': {
'type': 'object',
'name': 'outer2',
'properties': {
'inner2': {
'type': 'number',
'description': 'child description',
'notes': [
'child notes'
],
'tags': [
'child',
'api'
],
'required': true,
'minimum': 5,
'maximum': 10
}
}
}
}
};
expect(Properties.parseProperty('x', deepStructure)).to.deep.equal(deepStructureJSON);
done();
});
lab.test('parse description', (done) => {

@@ -456,6 +345,4 @@

lab.test('toParameters', (done) => {
lab.test('joiToSwaggerDefinition', (done) => {
const joiStructure = Joi.object({

@@ -480,56 +367,4 @@ a: Joi.number()

//console.log(JSON.stringify( Properties.joiToSwaggerDefinition(joiStructure, {}) ));
//console.log(JSON.stringify( Properties.toParameters(joiStructure , 'query') ));
const structureJSON = {
'a': {
'type': 'number',
'description': 'the first number',
'required': true
},
'b': {
'type': 'number',
'description': 'the second number',
'required': true
},
'operator': {
'type': 'string',
'description': 'the opertator i.e. + - / or *',
'required': true,
'default': '+'
},
'equals': {
'type': 'number',
'description': 'the result of the sum',
'required': true
}
};
expect(Properties.joiToSwaggerDefinition(joiStructure, 'query')).to.deep.equal(structureJSON);
done();
});
lab.test('joiToSwaggerParameters', (done) => {
const joiStructure = Joi.object({
a: Joi.number()
.required()
.description('the first number'),
b: Joi.number()
.required()
.description('the second number'),
operator: Joi.string()
.required()
.default('+')
.description('the opertator i.e. + - / or *'),
equals: Joi.number()
.required()
.description('the result of the sum')
});
//console.log(JSON.stringify( Properties.joiToSwaggerParameters(joiStructure , 'query') ));
const structureJSON = [

@@ -567,3 +402,3 @@ {

expect(Properties.joiToSwaggerParameters(joiStructure, 'query')).to.deep.equal(structureJSON);
expect(Properties.toParameters(joiStructure, {}, 'query')).to.deep.equal(structureJSON);
done();

@@ -576,1 +411,73 @@ });

});
lab.experiment('property deep - ', () => {
const deepStructure = Joi.object({
outer1: Joi.object({
inner1: Joi.string()
.description('child description')
.notes(['child notes'])
.tags(['child', 'api'])
.required()
}),
outer2: Joi.object({
inner2: Joi.number()
.description('child description')
.notes(['child notes'])
.tags(['child', 'api'])
.min(5)
.max(10)
.required()
})
});
lab.test('parse structure with child description, notes, name etc', (done) => {
const routes = [{
method: 'POST',
path: '/path/two',
config: {
tags: ['api'],
handler: Helper.defaultHandler,
response: {
schema: deepStructure
}
}
}];
Helper.createServer({}, routes, (err, server) => {
server.inject({ url: '/swagger.json' }, function (response) {
expect(err).to.equal(null);
//console.log(JSON.stringify(response.result.definitions));
expect(response.result.definitions.outer1).to.deep.equal({
'properties': {
'inner1': {
'description': 'child description',
'type': 'string',
'notes': [
'child notes'
],
'tags': [
'child',
'api'
]
}
},
'required': [
'inner1'
],
'type': 'object'
});
done();
});
});
});
});

@@ -165,3 +165,3 @@ 'use strict';

'schema': {
'$ref': '#/definitions/microformatsapi_payload'
'$ref': '#/definitions/parameters_microformatsapi_post'
}

@@ -383,3 +383,3 @@ }

},
'microformatsapi2_payload': {
'parameters_microformatsapi2_post': {
'properties': {

@@ -386,0 +386,0 @@ 'b': {

@@ -82,49 +82,2 @@ 'use strict';

const swaggerSumModel = {
'properties': {
'id': {
'type': 'string',
'example': 'x78P9c'
},
'a': {
'type': 'number',
'example': 5
},
'b': {
'type': 'number',
'example': 5
},
'operator': {
'type': 'string',
'example': '+',
'description': 'either +, -, /, or *'
},
'equals': {
'type': 'number',
'example': 10
},
'created': {
'type': 'string',
'example': '2015-12-01',
'description': 'ISO date string'
},
'modified': {
'type': 'string',
'example': '2015-12-01',
'description': 'ISO date string'
}
},
'description': 'json body for sum',
'required': [
'id',
'a',
'b',
'operator',
'equals',
'created'
],
'type': 'object'
};
lab.test('using hapi response.schema', (done) => {

@@ -160,11 +113,3 @@

//console.log(JSON.stringify(response.result));
expect(response.result.paths['/store/'].post.responses).to.deep.equal({
'200': {
'schema': {
'$ref': '#/definitions/Sum'
},
'description': 'Successful'
}
});
expect(response.result.definitions.Sum).to.deep.equal(swaggerSumModel);
expect(response.result.paths['/store/'].post.responses).to.exist();
done();

@@ -207,13 +152,4 @@ });

expect(err).to.equal(null);
expect(response.result.paths['/store/'].post.responses).to.deep.equal({
'200': {
'schema': {
'$ref': '#/definitions/List'
},
'description': 'Successful'
}
});
expect(response.result.definitions.List).to.exist();
expect(response.result.definitions.Sum).to.exist();
expect(response.result.definitions.List.properties.items.items.$ref).to.equal('#/definitions/Sum');
done();

@@ -258,8 +194,3 @@ });

//console.log(JSON.stringify(response.result));
expect(response.result.paths['/store/'].post.responses[200]).to.deep.equal({
'schema': {
'$ref': '#/definitions/Sum'
},
'description': 'Successful'
});
expect(response.result.paths['/store/'].post.responses[200]).to.exist();
expect(response.result.paths['/store/'].post.responses[400].description).to.equal('Bad Request');

@@ -317,3 +248,3 @@ expect(response.result.paths['/store/'].post.responses[400].headers).to.deep.equal(headers);

lab.test('using route base override', (done) => {
lab.test('using route base plugin override - object', (done) => {

@@ -347,3 +278,3 @@ const routes = {

//console.log(JSON.stringify(response.result));
expect(response.result.paths['/store/'].post.responses[200].schema).to.deep.equal({ '$ref': '#/definitions/Sum' });
expect(response.result.paths['/store/'].post.responses[200].schema).to.exist();
expect(response.result.paths['/store/'].post.responses[400].description).to.equal('Bad Request');

@@ -357,3 +288,3 @@ expect(response.result.paths['/store/'].post.responses[400].headers).to.deep.equal(headers);

lab.test('failback to default', (done) => {
lab.test('using route base plugin override - array', (done) => {

@@ -366,2 +297,15 @@ const routes = {

tags: ['api'],
plugins: {
'hapi-swagger': {
responses: {
'200': {
'description': 'Success',
'schema': Joi.array().items(Joi.object({
equals: Joi.number()
}).label('Result')).label('ResultSet')
},
'400': { 'description': 'Bad Request' }
}
}
},
validate: {

@@ -383,8 +327,19 @@ payload: {

//console.log(JSON.stringify(response.result));
expect(response.result.paths['/store/'].post.responses[200]).to.deep.equal({
'schema': {
'type': 'string'
expect(response.result.paths['/store/'].post.responses[200].schema).to.exist();
expect(response.result.definitions.ResultSet).to.deep.equal({
'type': 'array',
'items': {
'$ref': '#/definitions/Result'
}
});
expect(response.result.definitions.Result).to.deep.equal({
'properties': {
'equals': {
'type': 'number'
}
},
'description': 'Successful'
'type': 'object'
});
expect(response.result.paths['/store/'].post.responses[400].description).to.equal('Bad Request');
done();

@@ -396,2 +351,42 @@ });

lab.test('failback to 200', (done) => {
const routes = {
method: 'POST',
path: '/store/',
config: {
handler: Helper.defaultHandler,
tags: ['api'],
validate: {
payload: {
a: Joi.number()
.required()
.description('the first number')
}
}
}
};
Helper.createServer({}, routes, (err, server) => {
server.inject({ url: '/swagger.json' }, function (response) {
expect(err).to.equal(null);
//console.log(JSON.stringify(response.result));
expect(response.result.paths['/store/'].post.responses).to.deep.equal({
'200': {
'schema': {
'type': 'string'
},
'description': 'Successful'
}
});
done();
});
});
});
lab.test('No ownProperty', (done) => {

@@ -404,12 +399,20 @@

//console.log(JSON.stringify( Responses.build({},{},{},{}) ));
expect(Responses.build({}, {}, {}, {})).to.deep.equal({
200: {
'200': {
'schema': {
'type': 'string'
},
'description': 'Successful'
}
});
expect(Responses.build( objA,objB,objC,{ } )).to.deep.equal({
200: {
expect(Responses.build(objA, objB, objC, {})).to.deep.equal({
'200': {
'schema': {
'type': 'string'
},
'description': 'Successful'
}
});
objA[200] = { description : 'Successful' };

@@ -422,2 +425,86 @@ expect(Responses.build( objA,objB,objC,{ } )).to.deep.equal({ 200:{ 'description': 'Successful' } });

lab.test('with same path but different method', (done) => {
const routes = [{
method: 'POST',
path: '/path/two',
config: {
tags: ['api'],
handler: Helper.defaultHandler,
response: {
schema: {
value1111: Joi.boolean()
}
}
}
},{
method: 'GET',
path: '/path/two',
config: {
tags: ['api'],
handler: Helper.defaultHandler,
response: {
schema: Joi.object({
value2222: Joi.boolean()
})
}
}
}];
Helper.createServer({}, routes, (err, server) => {
server.inject({ url: '/swagger.json' }, function (response) {
expect(err).to.equal(null);
//console.log(JSON.stringify(response.result.definitions));
expect(response.result.definitions.response_pathtwo_get_200).to.exist();
expect(response.result.definitions.response_pathtwo_post_200).to.exist();
done();
});
});
});
lab.test('with deep labels', (done) => {
const routes = [{
method: 'POST',
path: '/path/two',
config: {
tags: ['api'],
handler: Helper.defaultHandler,
response: {
schema: Joi.object({
value1111: Joi.boolean()
}).label('labelA')
}
}
}];
Helper.createServer({}, routes, (err, server) => {
server.inject({ url: '/swagger.json' }, function (response) {
expect(err).to.equal(null);
// console.log(JSON.stringify(response.result.definitions));
expect(response.result.definitions.labelA).to.exist();
expect(response.result.definitions.response_pathtwo_post).to.exist();
done();
});
});
});
});

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

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