-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
141 lines (127 loc) · 4.73 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
134
135
136
137
138
139
140
141
var fileMagik = require('file-magik'),
express = require('express');
/**
* Performs automagic routing!
* @param opts
* .routesPath {String} The routes directory (default: 'routes')
* .recursive {Boolean} Recurse through entire routes directory (default: true)
* .routeOpts {Object} Data to pass to route handler. If array will use function.apply to "spread" arguments (default: {})
* .mountPath {String} The root path to mount the routes. Useful for multi-applications, or APIs (default: '/')
* .sortRoutes {Boolean) Whether to "sort" the returned routes, or keep original order. Note, object key ordering isn't guaranteed even when sorting due to the nature of JavaScript Objects
* .getRoutes {Boolean} Whether or not to perform route inspection/return (default: true)
* .convertDashedNames {Boolean} Convert dashed route handler names to camelCase for routing (default: true)
* @type {expressRoutify}
*/
var expressRoutify = module.exports = function expressRoutify(app, opts) {
if (!app) throw new Error('app not specified!');
opts = opts || {}; //optional
opts.routesPath = opts.routesPath || 'routes'; //optional
opts.recursive = typeof opts.recursive !== 'undefined' ? opts.recursive : true; //optional
opts.routeOpts = opts.routeOpts || {}; //optional
opts.mountPath = opts.mountPath || '/';
opts.sortRoutes = typeof opts.sortRoutes !== 'undefined' ? opts.sortRoutes : true;
opts.getRoutes = typeof opts.getRoutes !== 'undefined' ? opts.getRoutes : true;
var routePathMap = require('file-magik').mapPathsToObject(
{
path : opts.routesPath,
excludeFiles : opts.excludeFiles,
namespaceSubdirectories : opts.recursive
}
);
var routeObj = {};
routify(app, opts.mountPath, routePathMap, opts, routeObj);
if (opts.sortRoutes) {
return sortRoutes(routeObj);
}
return routeObj;
};
function routify(app, mountPath, routePathMap, opts, routeObj) {
// Sort to make sure `_` names get processed last. Otherwise route params could get confused with "higher level"
// routes in same folder. Object.keys doesn't necessarily return items "in order".
// TODO: Make order of params configuration option?
var routeNames = Object.keys(routePathMap).sort(function (a, b) {
if (a.match(/index/)) return 1;
return 0;
}).sort(function (a, b) {
if (a[0] === '_') { return 1; }
return 0;
});
for (var i = 0, iLen = routeNames.length; i < iLen; i++) {
var name = routeNames[i],
propertyValue = routePathMap[name];
var name = name[0] !== '_' ? name : ':' + name.substring(1);
if (typeof propertyValue !== 'string') {//handle sub-routes
if (opts.recursive) {
//routeObj[name] = {};
routify(app, mountPath + '/' + name, propertyValue, opts, routeObj);
}
continue;
}
var fileExports = require(propertyValue),
routeSuffix = name.toLowerCase() === 'index' ? '' : name,
router = express.Router({ mergeParams: true }),
routePath = mountPath + '/' + routeSuffix;
routePath = routePath.replace(/\/\//gi, '/');
if (!Array.isArray(opts.routeOpts)) {
var routing = fileExports(router, routePath, opts.routeOpts);
if (!routing) {
routing = expressRoutify.getVerbs(routePath, router)
}
app.use(routePath, router);
arrangeRoutes(routing, routeObj);
continue;
}
//allows passing parameters that are later named arguments
var routing = fileExports.apply(undefined, [router, routePath].concat(opts.routeOpts));
if (!routing) {
routing = this.getVerbs(routePath, router)
}
app.use(routePath, router);
arrangeRoutes(routing, routeObj);
}
}
function arrangeRoutes(routing, routeObj) {
if (routing) {
var urlIdxs = Object.keys(routing);
for (var j = 0, jlen = urlIdxs.length; j < jlen; j++) {
var routingObj = routing[j],
url = routingObj.url;
//handle setting or adding to url
var routeObjUrl = routeObj[url];
if (!routeObjUrl) {
routeObj[url] = routingObj;
continue;
}
var routingObjVerbIdxs = Object.keys(routingObj);
for (var k = 0, klen = routingObjVerbIdxs.length; k < klen; k++) {
var verbName = routingObjVerbIdxs[k],
verbData = routingObj[verbName];
if (verbName === 'url') continue;
if (!routeObjUrl[verbName]) {
routeObjUrl[verbName] = verbData;
continue;
}
if (Array.isArray(routeObjUrl[verbName])) {
routeObjUrl[verbName].push(verbData);
continue;
}
routeObjUrl[verbName] = [routeObjUrl[verbName], verbData];
}
}
}
}
function sortRoutes(routeObj) {
var urlIdxs = Object.keys(routeObj);
urlIdxs.sort(function (a,b) {
if (a < b) return 1;
if (b > b) return -1;
return 0;
});
var sortedRoutes = {};
for(var i = urlIdxs.length; i--;) {
var url = urlIdxs[i];
sortedRoutes[url] = routeObj[url];
}
return sortedRoutes;
}
expressRoutify.getVerbs = require('./lib/get-verbs');