@novice1/routing 1.0.11 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -1
- package/index.d.ts +5 -0
- package/lib/layer.js +123 -112
- package/lib/route/createLayers.js +39 -39
- package/lib/route/metadataMiddleware.js +32 -33
- package/lib/route.js +205 -205
- package/lib/router/authMethods.js +36 -32
- package/lib/router/editLayersMethods.js +11 -11
- package/lib/router/metaMethods.js +13 -13
- package/lib/router/validatorsMethods.js +36 -32
- package/lib/router.d.ts +433 -0
- package/lib/router.js +314 -315
- package/lib/utils/toArray.js +28 -27
- package/package.json +32 -29
- package/.github/workflows/nodejs.yml +0 -29
- package/test/config/testconfig.js +0 -17
- package/test/tests/00_setup.js +0 -3
- package/test/tests/01_test_register.js +0 -52
- package/test/tests/02_test_route_method.js +0 -29
- package/test/tests/03_test_auth.js +0 -73
- package/test/tests/04_test_set_validators.js +0 -74
- package/test/tests/05_test_set_pre_validators.js +0 -49
package/lib/router.js
CHANGED
|
@@ -1,316 +1,315 @@
|
|
|
1
|
-
var ExpressRouter = require("express").Router;
|
|
2
|
-
var flatten = require('array-flatten');
|
|
3
|
-
var methods = require("methods");
|
|
4
|
-
var debug = require('debug')('novice1:router');
|
|
5
|
-
|
|
6
|
-
// custom
|
|
7
|
-
var Layer = require("./layer");
|
|
8
|
-
var Route = require("./route");
|
|
9
|
-
|
|
10
|
-
// custom methods
|
|
11
|
-
var editLayersMethods = require('./router/editLayersMethods');
|
|
12
|
-
var authMethods = require('./router/authMethods');
|
|
13
|
-
var validatorsMethods = require('./router/validatorsMethods');
|
|
14
|
-
var metaMethods = require('./router/metaMethods');
|
|
15
|
-
|
|
16
|
-
// utils
|
|
17
|
-
var toArray = require('./utils/toArray');
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @classdesc Initialize a new `Router` with the given `options`.
|
|
21
|
-
* @class
|
|
22
|
-
* @augments ExpressRouter express/lib/router
|
|
23
|
-
*/
|
|
24
|
-
function Router() {
|
|
25
|
-
var router = ExpressRouter.apply(this, Array.from(arguments));
|
|
26
|
-
overrideRouterMethods(router);
|
|
27
|
-
addProperties(router);
|
|
28
|
-
return router;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** @inheritdoc */
|
|
32
|
-
function route(path) {
|
|
33
|
-
// add metadata in route
|
|
34
|
-
var meta = {};
|
|
35
|
-
|
|
36
|
-
// if path argument is an object with property 'path'
|
|
37
|
-
if (path && typeof path === "object" && path.path) {
|
|
38
|
-
Object.keys(path).forEach(p => {
|
|
39
|
-
switch (p) {
|
|
40
|
-
case "path":
|
|
41
|
-
break;
|
|
42
|
-
case "auth":
|
|
43
|
-
meta[p] = Boolean(path[p]);
|
|
44
|
-
break;
|
|
45
|
-
case "name":
|
|
46
|
-
case "description":
|
|
47
|
-
meta[p] = path[p];
|
|
48
|
-
if (typeof meta[p] !== "string") {
|
|
49
|
-
meta[p] = JSON.stringify(meta[p]);
|
|
50
|
-
}
|
|
51
|
-
break;
|
|
52
|
-
case "parameters":
|
|
53
|
-
case "responses":
|
|
54
|
-
if (path[p] && typeof path[p] === 'object')
|
|
55
|
-
meta[p] = path[p];
|
|
56
|
-
break;
|
|
57
|
-
case "tags":
|
|
58
|
-
if (!meta.tags) {
|
|
59
|
-
meta[p] = [];
|
|
60
|
-
}
|
|
61
|
-
toArray(path[p], "string").forEach(s => {
|
|
62
|
-
meta[p].push(s);
|
|
63
|
-
});
|
|
64
|
-
break;
|
|
65
|
-
case "afterAuth":
|
|
66
|
-
case "preValidators":
|
|
67
|
-
case "
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
var
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
* @
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
router.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* @
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
1
|
+
var ExpressRouter = require("express").Router;
|
|
2
|
+
var { flatten } = require('array-flatten');
|
|
3
|
+
var methods = require("methods");
|
|
4
|
+
var debug = require('debug')('novice1:router');
|
|
5
|
+
|
|
6
|
+
// custom
|
|
7
|
+
var Layer = require("./layer");
|
|
8
|
+
var Route = require("./route");
|
|
9
|
+
|
|
10
|
+
// custom methods
|
|
11
|
+
var editLayersMethods = require('./router/editLayersMethods');
|
|
12
|
+
var authMethods = require('./router/authMethods');
|
|
13
|
+
var validatorsMethods = require('./router/validatorsMethods');
|
|
14
|
+
var metaMethods = require('./router/metaMethods');
|
|
15
|
+
|
|
16
|
+
// utils
|
|
17
|
+
var toArray = require('./utils/toArray');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @classdesc Initialize a new `Router` with the given `options`.
|
|
21
|
+
* @class
|
|
22
|
+
* @augments ExpressRouter express/lib/router
|
|
23
|
+
*/
|
|
24
|
+
function Router() {
|
|
25
|
+
var router = ExpressRouter.apply(this, Array.from(arguments));
|
|
26
|
+
overrideRouterMethods(router);
|
|
27
|
+
addProperties(router);
|
|
28
|
+
return router;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** @inheritdoc */
|
|
32
|
+
function route(path) {
|
|
33
|
+
// add metadata in route
|
|
34
|
+
var meta = {};
|
|
35
|
+
|
|
36
|
+
// if path argument is an object with property 'path'
|
|
37
|
+
if (path && typeof path === "object" && !Array.isArray(path) && path.path) {
|
|
38
|
+
Object.keys(path).forEach(p => {
|
|
39
|
+
switch (p) {
|
|
40
|
+
case "path":
|
|
41
|
+
break;
|
|
42
|
+
case "auth":
|
|
43
|
+
meta[p] = Boolean(path[p]);
|
|
44
|
+
break;
|
|
45
|
+
case "name":
|
|
46
|
+
case "description":
|
|
47
|
+
meta[p] = path[p];
|
|
48
|
+
if (typeof meta[p] !== "string") {
|
|
49
|
+
meta[p] = JSON.stringify(meta[p]);
|
|
50
|
+
}
|
|
51
|
+
break;
|
|
52
|
+
case "parameters":
|
|
53
|
+
case "responses":
|
|
54
|
+
if (path[p] && typeof path[p] === 'object')
|
|
55
|
+
meta[p] = path[p];
|
|
56
|
+
break;
|
|
57
|
+
case "tags":
|
|
58
|
+
if (!meta.tags) {
|
|
59
|
+
meta[p] = [];
|
|
60
|
+
}
|
|
61
|
+
toArray(path[p], "string").forEach(s => {
|
|
62
|
+
meta[p].push(s);
|
|
63
|
+
});
|
|
64
|
+
break;
|
|
65
|
+
case "afterAuth":
|
|
66
|
+
case "preValidators":
|
|
67
|
+
case "preValidation":
|
|
68
|
+
if (!meta.preValidators) {
|
|
69
|
+
meta.preValidators = [];
|
|
70
|
+
}
|
|
71
|
+
toArray(path[p], "function").forEach(s => {
|
|
72
|
+
meta.preValidators.push(s);
|
|
73
|
+
});
|
|
74
|
+
if(!meta.preValidators.length) {
|
|
75
|
+
delete meta.preValidators;
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
// meta[p] = path[p];
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
path = path.path;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// initialize route
|
|
88
|
+
var route = new Route(path);
|
|
89
|
+
route.meta = meta;
|
|
90
|
+
|
|
91
|
+
// initialize layer
|
|
92
|
+
var layer = new Layer(
|
|
93
|
+
path,
|
|
94
|
+
{
|
|
95
|
+
sensitive: this.caseSensitive,
|
|
96
|
+
strict: this.strict,
|
|
97
|
+
end: true
|
|
98
|
+
},
|
|
99
|
+
route.dispatch.bind(route)
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
layer.route = route;
|
|
103
|
+
|
|
104
|
+
this.stack.push(layer);
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @todo code should be to work like '.route(...).get(...)'
|
|
108
|
+
// if there are:
|
|
109
|
+
// - 'auth' handlers
|
|
110
|
+
// - 'validators' handlers
|
|
111
|
+
[
|
|
112
|
+
{
|
|
113
|
+
prop: '_auth',
|
|
114
|
+
action: 'setAuth',
|
|
115
|
+
prop2: '_ifNoAuth',
|
|
116
|
+
action2: 'setAuthIfNone'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
prop: '_validators',
|
|
120
|
+
action: 'setValidators',
|
|
121
|
+
prop2: '_ifNoValidators',
|
|
122
|
+
action2: 'setValidatorsIfNone'
|
|
123
|
+
}
|
|
124
|
+
].forEach((v) => {
|
|
125
|
+
var executeAction = function (p, a) {
|
|
126
|
+
var handles = this[p].concat([]);
|
|
127
|
+
// add layer options
|
|
128
|
+
handles.unshift({
|
|
129
|
+
sensitive: this.caseSensitive,
|
|
130
|
+
strict: this.strict,
|
|
131
|
+
end: true
|
|
132
|
+
});
|
|
133
|
+
route[a].apply(route, handles);
|
|
134
|
+
};
|
|
135
|
+
if (this[v.prop].length) {
|
|
136
|
+
executeAction(v.prop, v.action);
|
|
137
|
+
} else if (v.prop2 && this[v.prop2].length) {
|
|
138
|
+
executeAction(v.prop2, v.action2);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
return route;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** @inheritdoc */
|
|
147
|
+
function use(fn) {
|
|
148
|
+
var offset = 0;
|
|
149
|
+
var path = '/';
|
|
150
|
+
|
|
151
|
+
// default path to '/'
|
|
152
|
+
// disambiguate router.use([fn])
|
|
153
|
+
if (typeof fn !== 'function') {
|
|
154
|
+
var arg = fn;
|
|
155
|
+
|
|
156
|
+
while (Array.isArray(arg) && arg.length !== 0) {
|
|
157
|
+
arg = arg[0];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// first arg is the path
|
|
161
|
+
if (typeof arg !== 'function') {
|
|
162
|
+
offset = 1;
|
|
163
|
+
path = fn;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
var callbacks = flatten(Array.prototype.slice.call(arguments, offset));
|
|
168
|
+
|
|
169
|
+
if (callbacks.length === 0) {
|
|
170
|
+
throw new TypeError('Router.use() requires a middleware function')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (var i = 0; i < callbacks.length; i++) {
|
|
174
|
+
var fn = callbacks[i];
|
|
175
|
+
|
|
176
|
+
if (typeof fn !== 'function') {
|
|
177
|
+
throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn))
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// add the middleware
|
|
181
|
+
debug('use %o %s', path, fn.name || '<anonymous>')
|
|
182
|
+
|
|
183
|
+
var layer = new Layer(path, {
|
|
184
|
+
sensitive: this.caseSensitive,
|
|
185
|
+
strict: false,
|
|
186
|
+
end: false
|
|
187
|
+
}, fn);
|
|
188
|
+
|
|
189
|
+
layer.route = undefined;
|
|
190
|
+
|
|
191
|
+
this.stack.push(layer);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return this;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @description Override methods of a router.
|
|
199
|
+
* @param {*} router
|
|
200
|
+
*/
|
|
201
|
+
function overrideRouterMethods(router) {
|
|
202
|
+
// override express Router's 'route' method
|
|
203
|
+
router.route = route;
|
|
204
|
+
router.use = use;
|
|
205
|
+
|
|
206
|
+
// override methods
|
|
207
|
+
methods.concat('all').forEach(function(method){
|
|
208
|
+
router[method] = function(path){
|
|
209
|
+
var route = this.route(path)
|
|
210
|
+
route[method].apply(route, Array.prototype.slice.call(arguments, 1));
|
|
211
|
+
|
|
212
|
+
[
|
|
213
|
+
// auth
|
|
214
|
+
{
|
|
215
|
+
prop: '_auth',
|
|
216
|
+
action: 'setAuth',
|
|
217
|
+
prop2: '_ifNoAuth' // @todo make use of it ?
|
|
218
|
+
},
|
|
219
|
+
// before validators / after auth
|
|
220
|
+
{
|
|
221
|
+
metaProp: 'preValidators',
|
|
222
|
+
action: 'setPreValidators'
|
|
223
|
+
},
|
|
224
|
+
// validators
|
|
225
|
+
{
|
|
226
|
+
prop: '_validators',
|
|
227
|
+
action: 'setValidators',
|
|
228
|
+
prop2: '_ifNoValidators' // @todo make use of it ?
|
|
229
|
+
}
|
|
230
|
+
].forEach((v) => {
|
|
231
|
+
var executeAction = (container, p, a) => {
|
|
232
|
+
var handles = container[p].concat([]);
|
|
233
|
+
// add layer options
|
|
234
|
+
handles.unshift({
|
|
235
|
+
sensitive: this.caseSensitive,
|
|
236
|
+
strict: this.strict,
|
|
237
|
+
end: true
|
|
238
|
+
});
|
|
239
|
+
route[a].apply(route, handles);
|
|
240
|
+
};
|
|
241
|
+
if (v.metaProp && route.meta[v.metaProp] &&route.meta[v.metaProp].length) {
|
|
242
|
+
executeAction(route.meta, v.metaProp, v.action);
|
|
243
|
+
delete route.meta[v.metaProp];
|
|
244
|
+
} else if (v.prop && this[v.prop].length) {
|
|
245
|
+
executeAction(this, v.prop, v.action);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
return this;
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @description Add properties to a router.
|
|
256
|
+
* @param {*} router
|
|
257
|
+
*/
|
|
258
|
+
function addProperties(router) {
|
|
259
|
+
// add '_auth' property to store handlers
|
|
260
|
+
Object.defineProperty(router, '_auth', {
|
|
261
|
+
value: [],
|
|
262
|
+
writable: true
|
|
263
|
+
});
|
|
264
|
+
// add '_validators' property to store handlers
|
|
265
|
+
Object.defineProperty(router, '_validators', {
|
|
266
|
+
value: [],
|
|
267
|
+
writable: true
|
|
268
|
+
});
|
|
269
|
+
// add '_ifNoAuth' property boolean
|
|
270
|
+
Object.defineProperty(router, '_ifNoAuth', {
|
|
271
|
+
value: false,
|
|
272
|
+
writable: true
|
|
273
|
+
});
|
|
274
|
+
// add '_ifNoValidators' property boolean
|
|
275
|
+
Object.defineProperty(router, '_ifNoValidators', {
|
|
276
|
+
value: false,
|
|
277
|
+
writable: true
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// add 'setAuthHandlers' method (stores handlers into '_auth')
|
|
281
|
+
Object.defineProperty(router, 'setAuthHandlers', {
|
|
282
|
+
value: authMethods.setAuthHandlers,
|
|
283
|
+
writable: true
|
|
284
|
+
});
|
|
285
|
+
// add 'setAuthHandlersIfNone' method (stores handlers into '_auth')
|
|
286
|
+
Object.defineProperty(router, 'setAuthHandlersIfNone', {
|
|
287
|
+
value: authMethods.setAuthHandlersIfNone,
|
|
288
|
+
writable: true
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// add 'setValidators' method (stores handlers into '_validators')
|
|
292
|
+
Object.defineProperty(router, 'setValidators', {
|
|
293
|
+
value: validatorsMethods.setValidators,
|
|
294
|
+
writable: true
|
|
295
|
+
});
|
|
296
|
+
// add 'setValidatorsIfNone' method (stores handlers into '_validators')
|
|
297
|
+
Object.defineProperty(router, 'setValidatorsIfNone', {
|
|
298
|
+
value: validatorsMethods.setValidatorsIfNone,
|
|
299
|
+
writable: true
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// add 'editLayers' method
|
|
303
|
+
Object.defineProperty(router, 'editLayers', {
|
|
304
|
+
value: editLayersMethods.editLayers,
|
|
305
|
+
writable: true
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// add 'getMeta' method
|
|
309
|
+
Object.defineProperty(router, 'getMeta', {
|
|
310
|
+
value: metaMethods.getMeta,
|
|
311
|
+
writable: true
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
316
315
|
module.exports = Router;
|