swagger-express-middleware
swagger-express-middleware copied to clipboard
mock middleware doesn't respect allOf
At first: Thank you so much for developing and sharing this awesome project - loving it!
With the 1.0.0-alpha.12 and the following yaml:
paths:
/applications:
get:
tags:
- applications
summary: Get all applications
responses:
'200':
description: List of applications
schema:
type: array
items:
$ref: '#/definitions/application'
post:
tags:
- applications
summary: Create a new application
consumes:
- application/json
parameters:
- in: body
name: properties
description: Properties of the application to create
schema:
type: object
allOf:
- $ref: '#/definitions/application'
- type: object
required: [type]
properties:
type:
readOnly: false
responses:
201:
description: application created
definitions:
application:
type: object
description: Information about an application
required:
- name
properties:
id:
type: integer
example: 2412
readOnly: true
type:
type: string
example: store
readOnly: true
name:
type: string
example: Store application 1
I get the following exception
TypeError: Cannot read property 'name' of undefined
at /srv/node_modules/swagger-express-middleware/lib/mock/edit-collection.js:226:28
at Array.some (<anonymous>)
at getResourceNameByName (/srv/node_modules/swagger-express-middleware/lib/mock/edit-collection.js:219:35)
at getResourceName (/srv/node_modules/swagger-express-middleware/lib/mock/edit-collection.js:150:9)
at createResources (/srv/node_modules/swagger-express-middleware/lib/mock/edit-collection.js:115:20)
at mergeCollection (/srv/node_modules/swagger-express-middleware/lib/mock/edit-collection.js:36:19)
at mockImplementation (/srv/node_modules/swagger-express-middleware/lib/mock/index.js:125:7)
at Layer.handle [as handle_request] (/srv/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/srv/node_modules/express/lib/router/index.js:317:13)
at /srv/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/srv/node_modules/express/lib/router/index.js:335:12)
at next (/srv/node_modules/express/lib/router/index.js:275:10)
at mockResponse (/srv/node_modules/swagger-express-middleware/lib/mock/index.js:100:5)
at Layer.handle [as handle_request] (/srv/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/srv/node_modules/express/lib/router/index.js:317:13)
at /srv/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/srv/node_modules/express/lib/router/index.js:335:12)
at next (/srv/node_modules/express/lib/router/index.js:275:10)
at http415 (/srv/node_modules/swagger-express-middleware/lib/request-validator.js:214:3)
at Layer.handle [as handle_request] (/srv/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/srv/node_modules/express/lib/router/index.js:317:13)
at /srv/node_modules/express/lib/router/index.js:284:7
when doing the POST request.
I can work around this by adding a properties object with the id property to the response schema object but that would be redundant and meaningless to swagger (swagger UI handles the above yaml as expected: the type property is required for the post request).
If you want I can try to do a PR but I'd need to know where it would be best to hook in and merge the allOf objects.
All the best, Christian
FWIMC, I worked around this with an addition to the callback:
const express = require('express')
const middleware = require('swagger-express-middleware')
const mergeWith = require('lodash.mergewith')
const app = express()
function expandAllOf (object) {
while (object.hasOwnProperty('allOf')) {
const allOf = object.allOf
delete object.allOf
const override = mergeWith({}, ...allOf, object, function (target, source) {
if (Array.isArray(target)) {
return target.concat(source).filter((v, i, a) => a.indexOf(v) === i)
}
if (typeof target === 'object') {
expandAllOf(target)
}
if (typeof source === 'object') {
expandAllOf(source)
}
})
Object.assign(object, override)
}
Object.keys(object).forEach((key) => {
if (typeof object[key] === 'object') {
expandAllOf(object[key])
}
})
}
middleware('PetStore.yaml', app, function(err, middleware, api) {
if (!err && api) {
expandAllOf(api.paths || {})
expandAllOf(api.definitions || {})
}
app.use(
middleware.metadata(),
middleware.CORS(),
middleware.files(),
middleware.parseRequest(),
middleware.validateRequest(),
middleware.mock()
);
app.listen(8000, function() {
console.log('The PetStore sample is now running at http://localhost:8000');
});
})
@BigstickCarpet any update on this functionality being implemented/improved?