-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathindex.js
133 lines (101 loc) · 3.97 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
var _ = require("underscore");
var express = require("express");
module.exports = function (app, mongoose) {
// Add an API endpoint to be used internally by this module
app.get('/api-docs', function (req, res) {
try {
if (app.routes) {
// Extract all API routes in one array in case of express3
var routes = _.flatten(app.routes);
}
else {
// Extract all API routes in one array in case of express4
var arr = [];
_.each(app._router.stack, function (route) {
if (!_.isUndefined(route.route)) {
route.route.method = Object.keys(route.route.methods).toString();
arr.push(route.route);
} else if(route.handle.stack) {
// Extract routes from middlewere installed Router
_.each(route.handle.stack, function (route) {
if (!_.isUndefined(route.route)) {
route.route.method = Object.keys(route.route.methods).toString();
arr.push(route.route);
}
});
}
});
routes = arr;
}
// Group routes by resource name
routes = _.groupBy(routes, function (route) {
return route.path.split("/")[1];
});
// Skip the routes to be used internally by this module
delete routes['api-docs'];
// Transform route groups object to an array of group/routes pairs
routes = _.pairs(routes);
var schemas;
if (mongoose)
schemas = generateSchemaDocs(mongoose);
res.send({routes: routes, schemas: schemas});
} catch (e) {
res.send(400,e);
}
});
// Configure the directory which holds html docs template
app.use(express.static(__dirname + '/html'));
};
var nestedSchemas;
// Transform mongoose model schemas into a readable format
function generateSchemaDocs(mongoose) {
nestedSchemas = [];
// Transform models object to an array
var schemas = _.pairs(mongoose.modelSchemas);
// Map each schema to a readable format
schemas = _.map(schemas, function (schema) {
var info = getSchemaInfo(schema);
return info;
});
// Add nested schemas
schemas = schemas.concat(nestedSchemas);
return schemas;
}
function getSchemaInfo(schema) {
// Extract schema info for all fields of a schema
var paths = _.map(schema[1].paths, function (path) {
// Extract field info like type, required, enum etc.
var info = getFieldInfo(path);
// If field is a nested array with a custom, add it's schema to nested schemas
if (info && info.schema)
nestedSchemas.push(info.schema);
return info;
});
// Add virtual fields to schema info
_.each(schema[1].virtuals, function (virtual) {
if (virtual.path != "id")
paths.push({name: virtual.path, type: "Unknown"});
});
return {name: schema[0], fields: paths};
}
function getFieldInfo(path) {
var field = {name: path.path, type: path.instance};
if (path.options.type) {
field.type = path.options.type.name;
if (path.options.type instanceof Array && !path.schema)
field.type = path.options.type[0].name + " []";
}
field.min = path.options.min;
field.max = path.options.max;
if (path.enumValues && path.enumValues.length > 0)
field.enumValues = path.enumValues;
if (path.schema) {
// This field is a nested array with a custom schema
field.type = field.name;
// Get schema info for the array item schema
field.schema = getSchemaInfo([field.name, path.schema]);
}
if (path.isRequired)
field.required = true;
return field;
}