express-swagger-generator
Advanced tools
Comparing version 1.1.3 to 1.1.4
@@ -25,84 +25,84 @@ /** | ||
function parseApiFile(file) { | ||
const content = fs.readFileSync(file, 'utf-8'); | ||
const content = fs.readFileSync(file, 'utf-8'); | ||
let comments = doctrineFile.parseFileContent(content, {unwrap: true, sloppy: true, tags: null, recoverable: true}); | ||
return comments; | ||
let comments = doctrineFile.parseFileContent(content, {unwrap: true, sloppy: true, tags: null, recoverable: true}); | ||
return comments; | ||
} | ||
function parseRoute(str) { | ||
let split = str.split(" ") | ||
let split = str.split(" ") | ||
return { | ||
method: split[0].toLowerCase() || 'get', | ||
uri: split[1] || '' | ||
} | ||
return { | ||
method: split[0].toLowerCase() || 'get', | ||
uri: split[1] || '' | ||
} | ||
} | ||
function parseField(str) { | ||
let split = str.split(".") | ||
return { | ||
name: split[0], | ||
parameter_type: split[1] || 'get', | ||
required: split[2] && split[2] === 'required' || false | ||
} | ||
let split = str.split(".") | ||
return { | ||
name: split[0], | ||
parameter_type: split[1] || 'get', | ||
required: split[2] && split[2] === 'required' || false | ||
} | ||
} | ||
function parseType(obj) { | ||
if(!obj) return undefined; | ||
if(obj.name) { | ||
const spl = obj.name.split('.'); | ||
if(spl.length > 1 && spl[1] == 'model'){ | ||
return spl[0]; | ||
} | ||
else return obj.name; | ||
} else if (obj.expression && obj.expression.name) { | ||
return obj.expression.name.toLowerCase(); | ||
} else { | ||
return 'string'; | ||
} | ||
if(!obj) return undefined; | ||
if(obj.name) { | ||
const spl = obj.name.split('.'); | ||
if(spl.length > 1 && spl[1] == 'model'){ | ||
return spl[0]; | ||
} | ||
else return obj.name; | ||
} else if (obj.expression && obj.expression.name) { | ||
return obj.expression.name.toLowerCase(); | ||
} else { | ||
return 'string'; | ||
} | ||
} | ||
function parseSchema(obj){ | ||
if(!obj.name) return undefined; | ||
const spl = obj.name.split('.'); | ||
if(spl.length > 1 && spl[1] == 'model'){ | ||
return { "$ref": "#/definitions/" + spl[0] }; | ||
} | ||
else return undefined; | ||
if(!obj.name) return undefined; | ||
const spl = obj.name.split('.'); | ||
if(spl.length > 1 && spl[1] == 'model'){ | ||
return { "$ref": "#/definitions/" + spl[0] }; | ||
} | ||
else return undefined; | ||
} | ||
function parseItems(obj) { | ||
if(obj.applications && obj.applications.length > 0 && obj.applications[0].name) { | ||
const type = obj.applications[0].name; | ||
if (type == 'object' || type == 'string' || type == 'integer' || type == 'boolean') { | ||
return { "type": type } | ||
} | ||
else return { "$ref": "#/definitions/" + type}; | ||
} | ||
else return undefined; | ||
if(obj.applications && obj.applications.length > 0 && obj.applications[0].name) { | ||
const type = obj.applications[0].name; | ||
if (type == 'object' || type == 'string' || type == 'integer' || type == 'boolean') { | ||
return { "type": type } | ||
} | ||
else return { "$ref": "#/definitions/" + type}; | ||
} | ||
else return undefined; | ||
} | ||
function parseReturn(tags) { | ||
let rets = {} | ||
for (let i in tags) { | ||
if (tags[i]['title'] == 'returns' || tags[i]['title'] == 'return') { | ||
let description = tags[i]['description'].split("-") | ||
rets[description[0]] = {description: description[1]}; | ||
const type = parseType(tags[i].type); | ||
if(type){ | ||
// rets[description[0]].type = type; | ||
rets[description[0]].schema = parseSchema(tags[i].type) | ||
} | ||
} | ||
} | ||
return rets | ||
let rets = {} | ||
for (let i in tags) { | ||
if (tags[i]['title'] == 'returns' || tags[i]['title'] == 'return') { | ||
let description = tags[i]['description'].split("-") | ||
rets[description[0]] = {description: description[1]}; | ||
const type = parseType(tags[i].type); | ||
if(type){ | ||
// rets[description[0]].type = type; | ||
rets[description[0]].schema = parseSchema(tags[i].type) | ||
} | ||
} | ||
} | ||
return rets | ||
} | ||
function parseDescription(obj) { | ||
return obj.description || '' | ||
return obj.description || '' | ||
} | ||
function parseTag(tags) { | ||
for (let i in tags) { | ||
if (tags[i]['title'] == 'group') { | ||
return tags[i]['description'].split("-") | ||
} | ||
} | ||
return ['default', ''] | ||
for (let i in tags) { | ||
if (tags[i]['title'] == 'group') { | ||
return tags[i]['description'].split("-") | ||
} | ||
} | ||
return ['default', ''] | ||
} | ||
function parseProduces(str) { | ||
return str.split(/\s+/); | ||
return str.split(/\s+/); | ||
} | ||
@@ -112,101 +112,118 @@ | ||
function parseConsumes(str) { | ||
return str.split(/\s+/); | ||
return str.split(/\s+/); | ||
} | ||
function parseTypedef(tags){ | ||
const typeName = tags[0]['name']; | ||
let details = { | ||
required: [], | ||
properties: {} | ||
}; | ||
if (tags[0].type && tags[0].type.name) { | ||
details.allOf = [ { "$ref": '#/definitions/' + tags[0].type.name} ] | ||
} | ||
for(let i = 1; i < tags.length; i++){ | ||
if(tags[i].title == 'property'){ | ||
let propName = tags[i].name; | ||
const required = propName.split('.')[1]; | ||
if(required && required == 'required'){ | ||
propName = propName.split('.')[0]; | ||
details.required.push(propName); | ||
} | ||
var schema = parseSchema(tags[i].type); | ||
if (schema) { | ||
details.properties[propName] = schema; | ||
} else { | ||
details.properties[propName] = { | ||
type: parseType(tags[i].type), | ||
description: tags[i].description || '', | ||
items: parseItems(tags[i].type) | ||
}; | ||
} | ||
} | ||
} | ||
return {typeName, details}; | ||
const typeName = tags[0]['name']; | ||
let details = { | ||
required: [], | ||
properties: {} | ||
}; | ||
if (tags[0].type && tags[0].type.name) { | ||
details.allOf = [ { "$ref": '#/definitions/' + tags[0].type.name} ] | ||
} | ||
for(let i = 1; i < tags.length; i++){ | ||
if(tags[i].title == 'property'){ | ||
let propName = tags[i].name; | ||
const required = propName.split('.')[1]; | ||
if(required && required == 'required'){ | ||
propName = propName.split('.')[0]; | ||
details.required.push(propName); | ||
} | ||
var schema = parseSchema(tags[i].type); | ||
if (schema) { | ||
details.properties[propName] = schema; | ||
} else { | ||
details.properties[propName] = { | ||
type: parseType(tags[i].type), | ||
description: tags[i].description || '', | ||
items: parseItems(tags[i].type) | ||
}; | ||
} | ||
} | ||
} | ||
return {typeName, details}; | ||
} | ||
function parseSecurity(comments) { | ||
let security; | ||
try { | ||
security = JSON.parse(comments) | ||
} catch(e){ | ||
let obj = {} | ||
obj[comments] = [] | ||
security = [ | ||
obj | ||
] | ||
} | ||
return security | ||
} | ||
function fileFormat(comments) { | ||
let route, parameters = {}, params = [], tags = [], definitions = {}; | ||
for (let i in comments) { | ||
let desc = parseDescription(comments); | ||
if (i == 'tags') { | ||
if(comments[i].length > 0 && comments[i][0]['title'] && comments[i][0]['title'] == 'typedef'){ | ||
let route, parameters = {}, params = [], tags = [], definitions = {}; | ||
for (let i in comments) { | ||
let desc = parseDescription(comments); | ||
if (i == 'tags') { | ||
if(comments[i].length > 0 && comments[i][0]['title'] && comments[i][0]['title'] == 'typedef'){ | ||
const typedefParsed = parseTypedef(comments[i]); | ||
definitions[typedefParsed.typeName] = typedefParsed.details; | ||
continue; | ||
} | ||
for (let j in comments[i]) { | ||
let title = comments[i][j]['title'] | ||
if (title == 'route') { | ||
route = parseRoute(comments[i][j]['description']) | ||
let tag = parseTag(comments[i]) | ||
parameters[route.uri] = parameters[route.uri] || {} | ||
parameters[route.uri][route.method] = parameters[route.uri][route.method] || {} | ||
parameters[route.uri][route.method]['parameters'] = [] | ||
parameters[route.uri][route.method]['description'] = desc | ||
parameters[route.uri][route.method]['tags'] = [tag[0]] | ||
tags.push({ | ||
name: tag[0], | ||
description: tag[1] | ||
}) | ||
} | ||
if (title == 'param') { | ||
let field = parseField(comments[i][j]['name']) | ||
params.push({ | ||
name: field.name, | ||
in: field.parameter_type, | ||
description: comments[i][j]['description'], | ||
required: field.required, | ||
type: parseType(comments[i][j]['type']), | ||
schema: parseSchema(comments[i][j]['type']) | ||
}) | ||
} | ||
const typedefParsed = parseTypedef(comments[i]); | ||
definitions[typedefParsed.typeName] = typedefParsed.details; | ||
continue; | ||
} | ||
for (let j in comments[i]) { | ||
let title = comments[i][j]['title'] | ||
if (title == 'route') { | ||
route = parseRoute(comments[i][j]['description']) | ||
let tag = parseTag(comments[i]) | ||
parameters[route.uri] = parameters[route.uri] || {} | ||
parameters[route.uri][route.method] = parameters[route.uri][route.method] || {} | ||
parameters[route.uri][route.method]['parameters'] = [] | ||
parameters[route.uri][route.method]['description'] = desc | ||
parameters[route.uri][route.method]['tags'] = [tag[0]] | ||
tags.push({ | ||
name: tag[0], | ||
description: tag[1] | ||
}) | ||
} | ||
if (title == 'param') { | ||
let field = parseField(comments[i][j]['name']) | ||
params.push({ | ||
name: field.name, | ||
in: field.parameter_type, | ||
description: comments[i][j]['description'], | ||
required: field.required, | ||
type: parseType(comments[i][j]['type']), | ||
schema: parseSchema(comments[i][j]['type']) | ||
}) | ||
} | ||
if (title == 'operationId' && route) { | ||
parameters[route.uri][route.method]['operationId'] = comments[i][j]['description']; | ||
} | ||
if (title == 'operationId' && route) { | ||
parameters[route.uri][route.method]['operationId'] = comments[i][j]['description']; | ||
} | ||
if (title == 'summary' && route) { | ||
parameters[route.uri][route.method]['summary'] = comments[i][j]['description']; | ||
} | ||
if (title == 'summary' && route) { | ||
parameters[route.uri][route.method]['summary'] = comments[i][j]['description']; | ||
} | ||
if (title == 'produces' && route) { | ||
parameters[route.uri][route.method]['produces'] = parseProduces(comments[i][j]['description']); | ||
} | ||
if (title == 'produces' && route) { | ||
parameters[route.uri][route.method]['produces'] = parseProduces(comments[i][j]['description']); | ||
} | ||
if (title == 'consumes' && route) { | ||
parameters[route.uri][route.method]['consumes'] = parseConsumes(comments[i][j]['description']); | ||
} | ||
if (title == 'consumes' && route) { | ||
parameters[route.uri][route.method]['consumes'] = parseConsumes(comments[i][j]['description']); | ||
} | ||
if (route) { | ||
parameters[route.uri][route.method]['parameters'] = params; | ||
parameters[route.uri][route.method]['responses'] = parseReturn(comments[i]); | ||
} | ||
} | ||
} | ||
} | ||
return {parameters: parameters, tags: tags, definitions: definitions} | ||
if(title == 'security' && route) { | ||
parameters[route.uri][route.method]['security'] = parseSecurity(comments[i][j]['description']) | ||
} | ||
if (route) { | ||
parameters[route.uri][route.method]['parameters'] = params; | ||
parameters[route.uri][route.method]['responses'] = parseReturn(comments[i]); | ||
} | ||
} | ||
} | ||
} | ||
return {parameters: parameters, tags: tags, definitions: definitions} | ||
} | ||
@@ -222,5 +239,5 @@ | ||
function filterJsDocComments(jsDocComments) { | ||
return jsDocComments.filter(function (item) { | ||
return item.tags.length > 0 | ||
}) | ||
return jsDocComments.filter(function (item) { | ||
return item.tags.length > 0 | ||
}) | ||
} | ||
@@ -236,6 +253,6 @@ | ||
function convertGlobPaths(base, globs) { | ||
return globs.reduce(function (acc, globString) { | ||
let globFiles = glob.sync(path.resolve(base, globString)); | ||
return acc.concat(globFiles); | ||
}, []); | ||
return globs.reduce(function (acc, globString) { | ||
let globFiles = glob.sync(path.resolve(base, globString)); | ||
return acc.concat(globFiles); | ||
}, []); | ||
} | ||
@@ -252,42 +269,42 @@ | ||
return function (options) { | ||
/* istanbul ignore if */ | ||
if (!options) { | ||
throw new Error('\'options\' is required.'); | ||
} else /* istanbul ignore if */ if (!options.swaggerDefinition) { | ||
throw new Error('\'swaggerDefinition\' is required.'); | ||
} else /* istanbul ignore if */ if (!options.files) { | ||
throw new Error('\'files\' is required.'); | ||
} | ||
return function (options) { | ||
/* istanbul ignore if */ | ||
if (!options) { | ||
throw new Error('\'options\' is required.'); | ||
} else /* istanbul ignore if */ if (!options.swaggerDefinition) { | ||
throw new Error('\'swaggerDefinition\' is required.'); | ||
} else /* istanbul ignore if */ if (!options.files) { | ||
throw new Error('\'files\' is required.'); | ||
} | ||
// Build basic swagger json | ||
let swaggerObject = swaggerHelpers.swaggerizeObj(options.swaggerDefinition); | ||
let apiFiles = convertGlobPaths(options.basedir, options.files); | ||
// Build basic swagger json | ||
let swaggerObject = swaggerHelpers.swaggerizeObj(options.swaggerDefinition); | ||
let apiFiles = convertGlobPaths(options.basedir, options.files); | ||
// Parse the documentation in the APIs array. | ||
for (let i = 0; i < apiFiles.length; i = i + 1) { | ||
let parsedFile = parseApiFile(apiFiles[i]); | ||
//console.log(JSON.stringify(parsedFile)) | ||
let comments = filterJsDocComments(parsedFile); | ||
// Parse the documentation in the APIs array. | ||
for (let i = 0; i < apiFiles.length; i = i + 1) { | ||
let parsedFile = parseApiFile(apiFiles[i]); | ||
//console.log(JSON.stringify(parsedFile)) | ||
let comments = filterJsDocComments(parsedFile); | ||
for (let j in comments) { | ||
for (let j in comments) { | ||
let parsed = fileFormat(comments[j]) | ||
swaggerHelpers.addDataToSwaggerObject(swaggerObject, [{paths: parsed.parameters, tags: parsed.tags, definitions: parsed.definitions}]); | ||
} | ||
} | ||
let parsed = fileFormat(comments[j]) | ||
swaggerHelpers.addDataToSwaggerObject(swaggerObject, [{paths: parsed.parameters, tags: parsed.tags, definitions: parsed.definitions}]); | ||
} | ||
} | ||
parser.parse(swaggerObject, function (err, api) { | ||
if (!err) { | ||
swaggerObject = api; | ||
} | ||
}); | ||
app.use('/api-docs.json', function (req, res) { | ||
res.json(swaggerObject); | ||
}); | ||
app.use('/api-docs', swaggerUi({ | ||
docs: '/api-docs.json' // from the express route above. | ||
})); | ||
return swaggerObject; | ||
} | ||
parser.parse(swaggerObject, function (err, api) { | ||
if (!err) { | ||
swaggerObject = api; | ||
} | ||
}); | ||
app.use('/api-docs.json', function (req, res) { | ||
res.json(swaggerObject); | ||
}); | ||
app.use('/api-docs', swaggerUi({ | ||
docs: '/api-docs.json' // from the express route above. | ||
})); | ||
return swaggerObject; | ||
} | ||
}; |
{ | ||
"name": "express-swagger-generator", | ||
"version": "1.1.3", | ||
"version": "1.1.4", | ||
"description": "Generates swagger doc & ui based on express existing routes.", | ||
@@ -30,3 +30,3 @@ "main": "index.js", | ||
"doctrine-file": "^1.0.2", | ||
"express-swaggerize-ui": "^1.0.0" | ||
"express-swaggerize-ui": "^1.0.2" | ||
}, | ||
@@ -33,0 +33,0 @@ "devDependencies": { |
@@ -29,3 +29,11 @@ ### Express Swagger Generator | ||
], | ||
schemes: ['http', 'https'] | ||
schemes: ['http', 'https'], | ||
securityDefinitions: { | ||
JWT: { | ||
type: 'apiKey', | ||
in: 'header', | ||
name: 'Authorization', | ||
description: "", | ||
} | ||
} | ||
}, | ||
@@ -97,2 +105,3 @@ basedir: __dirname, //app absolute path | ||
* @returns {Product.model} default - Unexpected error | ||
* @security JWT | ||
*/ | ||
@@ -99,0 +108,0 @@ ``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
21776
520
110
Updatedexpress-swaggerize-ui@^1.0.2