adapt-authoring-server 0.0.1 → 1.0.0
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/.eslintignore +1 -1
- package/.eslintrc +14 -14
- package/.github/ISSUE_TEMPLATE/bug_report.yml +55 -55
- package/.github/ISSUE_TEMPLATE/feature_request.yml +22 -22
- package/.github/dependabot.yml +11 -11
- package/.github/pull_request_template.md +25 -25
- package/.github/workflows/new.yml +19 -19
- package/.github/workflows/releases.yml +25 -0
- package/adapt-authoring.json +8 -8
- package/conf/config.schema.json +38 -38
- package/docs/server-requests.md +28 -28
- package/errors/errors.json +23 -23
- package/index.js +5 -5
- package/lib/Router.js +272 -272
- package/lib/ServerModule.js +153 -153
- package/lib/ServerUtils.js +191 -191
- package/lib/typedefs.js +57 -57
- package/package.json +57 -22
- package/tests/router.spec.js +142 -142
- package/tests/serverModule.spec.js +51 -51
package/lib/Router.js
CHANGED
|
@@ -1,272 +1,272 @@
|
|
|
1
|
-
import _ from 'lodash'
|
|
2
|
-
import { App } from 'adapt-authoring-core'
|
|
3
|
-
import express from 'express'
|
|
4
|
-
import ServerUtils from './ServerUtils.js'
|
|
5
|
-
/**
|
|
6
|
-
* Handles the Express routing functionality
|
|
7
|
-
* @memberof server
|
|
8
|
-
*/
|
|
9
|
-
class Router {
|
|
10
|
-
/**
|
|
11
|
-
* If passing an {@link ExpressRouter} as the parentRouter, it is assumed that the Express Router is the top of the router 'heirarchy' (which will have an impact of some of the {@link Router} methods)
|
|
12
|
-
* @param {String} root Route API endpoint for this router
|
|
13
|
-
* @param {Router|ExpressRouter} parentRouter Parent to mount router
|
|
14
|
-
* @param {Array<Route>} routes Array of routes
|
|
15
|
-
*/
|
|
16
|
-
constructor (root, parentRouter, routes) {
|
|
17
|
-
/**
|
|
18
|
-
* The root route the router will be mounted at
|
|
19
|
-
* @type {String}
|
|
20
|
-
*/
|
|
21
|
-
this.root = root
|
|
22
|
-
/**
|
|
23
|
-
* Routes config
|
|
24
|
-
* @type {Array<Route>}
|
|
25
|
-
*/
|
|
26
|
-
this.routes = routes ?? []
|
|
27
|
-
/**
|
|
28
|
-
* Express router instance
|
|
29
|
-
* @type {external:ExpressRouter}
|
|
30
|
-
*/
|
|
31
|
-
this.expressRouter = express.Router()
|
|
32
|
-
/**
|
|
33
|
-
* Express router instance
|
|
34
|
-
* @type {ExpressApp|Router}
|
|
35
|
-
*/
|
|
36
|
-
this.parentRouter = parentRouter
|
|
37
|
-
/**
|
|
38
|
-
* List of sub-routers
|
|
39
|
-
* @type {Array<Router>}
|
|
40
|
-
*/
|
|
41
|
-
this.childRouters = []
|
|
42
|
-
/**
|
|
43
|
-
* Middleware stack to be added directly to the router
|
|
44
|
-
* @type {Array<Function>}
|
|
45
|
-
*/
|
|
46
|
-
this.routerMiddleware = [
|
|
47
|
-
ServerUtils.addErrorHandler
|
|
48
|
-
]
|
|
49
|
-
/**
|
|
50
|
-
* Middleware stack to be added before route handlers (useful if you need access to specific request attributes that don't exist when standard middleware runs)
|
|
51
|
-
* @type {Array<Function>}
|
|
52
|
-
*/
|
|
53
|
-
this.handlerMiddleware = [
|
|
54
|
-
ServerUtils.addExistenceProps,
|
|
55
|
-
ServerUtils.handleInternalRoutes
|
|
56
|
-
]
|
|
57
|
-
/** @ignore */this._initialised = false
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Returns the map of routes attached to this router
|
|
62
|
-
* @type {Object}
|
|
63
|
-
*/
|
|
64
|
-
get map () {
|
|
65
|
-
return ServerUtils.generateRouterMap(this)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Generates this router's path from its ancestors
|
|
70
|
-
* @type {String}
|
|
71
|
-
*/
|
|
72
|
-
get path () {
|
|
73
|
-
let p = ''
|
|
74
|
-
|
|
75
|
-
if (_.isString(this.parentRouter.path)) {
|
|
76
|
-
p += this.parentRouter.path
|
|
77
|
-
}
|
|
78
|
-
if (p[p.length - 1] !== '/' && this.root[0] !== '/') {
|
|
79
|
-
p += '/'
|
|
80
|
-
}
|
|
81
|
-
return p + this.root
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Returns the URL for the router
|
|
86
|
-
* @return {String} The URL
|
|
87
|
-
*/
|
|
88
|
-
get url () {
|
|
89
|
-
try {
|
|
90
|
-
const serverUrl = App.instance.dependencyloader.instances['adapt-authoring-server'].url
|
|
91
|
-
return serverUrl + this.path
|
|
92
|
-
} catch (e) {
|
|
93
|
-
this.log('error', e)
|
|
94
|
-
return ''
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Adds middleware to the router stack. Accepts multiple params.
|
|
100
|
-
* @param {...Function} func Middleware function(s) to be added
|
|
101
|
-
* @return {AbstractApiModule} This instance, for chaining
|
|
102
|
-
* @see https://expressjs.com/en/guide/using-middleware.html
|
|
103
|
-
*/
|
|
104
|
-
addMiddleware (...func) {
|
|
105
|
-
return this._addMiddleware(this.routerMiddleware, ...func)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Adds middleware to be called prior to any route handlers. Accepts multiple params. Useful if you need access to specific request attributes that don't exist when standard middleware runs.
|
|
110
|
-
* @param {...Function} func Middleware function(s) to be added
|
|
111
|
-
* @return {AbstractApiModule} This instance, for chaining
|
|
112
|
-
* @see https://expressjs.com/en/guide/using-middleware.html
|
|
113
|
-
*/
|
|
114
|
-
addHandlerMiddleware (...func) {
|
|
115
|
-
return this._addMiddleware(this.handlerMiddleware, ...func)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** @ignore */ _addMiddleware (stack, ...func) {
|
|
119
|
-
if (func.length) {
|
|
120
|
-
this.warnOnInited('middleware may not be called before any route handlers')
|
|
121
|
-
func.forEach(f => _.isFunction(f) && !stack.includes(f) && stack.push(f))
|
|
122
|
-
}
|
|
123
|
-
return this
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Recursively gets middleware of the current router heirarchy
|
|
128
|
-
* @param {Router} router The current router (used when run recursively)
|
|
129
|
-
* @param {Array<function>} middleware Middleware function(s) (used when run recursively)
|
|
130
|
-
* @return {Array<Function>}
|
|
131
|
-
*/
|
|
132
|
-
getHandlerMiddleware (router = this, middleware = []) {
|
|
133
|
-
if (!(router instanceof Router)) {
|
|
134
|
-
return middleware
|
|
135
|
-
}
|
|
136
|
-
return _.uniq(this.getHandlerMiddleware(router.parentRouter, [...router.handlerMiddleware, ...middleware]))
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Store route definition. Accepts multiple params.
|
|
141
|
-
* @param {...Route} route Config of route(s) to be added
|
|
142
|
-
* @return {AbstractApiModule} This instance, for chaining
|
|
143
|
-
*/
|
|
144
|
-
addRoute (...route) {
|
|
145
|
-
const inited = this.warnOnInited(`cannot set further routes (${this.path} ${route.map(r => r.route).join(', ')})`)
|
|
146
|
-
if (!inited && route.length) {
|
|
147
|
-
this.routes.push(...route.filter(this.validateRoute, this))
|
|
148
|
-
}
|
|
149
|
-
return this
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Function for filtering bad route configs
|
|
154
|
-
* @param {Route} r Route config
|
|
155
|
-
* @return {Boolean}
|
|
156
|
-
*/
|
|
157
|
-
validateRoute (r) {
|
|
158
|
-
const ePrefix = `invalid route config for ${this.route} router`
|
|
159
|
-
if (!_.isString(r.route)) {
|
|
160
|
-
this.log('warn', `${ePrefix}, route must be a string`)
|
|
161
|
-
return false
|
|
162
|
-
}
|
|
163
|
-
if (!r.handlers) {
|
|
164
|
-
this.log('warn', `${ePrefix}, no route handlers defined`)
|
|
165
|
-
return false
|
|
166
|
-
}
|
|
167
|
-
// handlers can be single function or array of functions
|
|
168
|
-
const allHandlersFuncs = Object.entries(r.handlers).every(([m, h]) => {
|
|
169
|
-
if (this.expressRouter[m] === undefined) {
|
|
170
|
-
this.log('warn', `${ePrefix}, ${m} must be a valid Express.js function`)
|
|
171
|
-
return false
|
|
172
|
-
}
|
|
173
|
-
if (!_.isFunction(h) && !(_.isArray(h) && h.every(_.isFunction))) {
|
|
174
|
-
this.log('warn', `${ePrefix} ${m.toUpperCase()} ${r.route}, all route handlers must be functions`)
|
|
175
|
-
return false
|
|
176
|
-
}
|
|
177
|
-
return true
|
|
178
|
-
})
|
|
179
|
-
if (!allHandlersFuncs) {
|
|
180
|
-
return false
|
|
181
|
-
}
|
|
182
|
-
return true
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Creates and adds a sub-router to this router.
|
|
187
|
-
* @param {string} root The root of the child router
|
|
188
|
-
* @param {Array<Route>} routes Array of Routes to add
|
|
189
|
-
* @return {Router} The new router instance
|
|
190
|
-
*/
|
|
191
|
-
createChildRouter (root, routes) {
|
|
192
|
-
if (this.warnOnInited(`cannot create further child routers (${this.path}/${root})`)) {
|
|
193
|
-
return this
|
|
194
|
-
}
|
|
195
|
-
const router = new Router(root, this, routes)
|
|
196
|
-
|
|
197
|
-
this.childRouters.push(router)
|
|
198
|
-
|
|
199
|
-
this.log('debug', 'ADD_ROUTER', router.path)
|
|
200
|
-
|
|
201
|
-
return router
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Initialises the API
|
|
206
|
-
*/
|
|
207
|
-
init () {
|
|
208
|
-
if (this.warnOnInited(`(${this.path})`)) {
|
|
209
|
-
return
|
|
210
|
-
}
|
|
211
|
-
if (this.routerMiddleware.length) {
|
|
212
|
-
this.expressRouter.use(...this.routerMiddleware)
|
|
213
|
-
}
|
|
214
|
-
if (this.childRouters.length) {
|
|
215
|
-
this.childRouters.forEach(c => {
|
|
216
|
-
c.init()
|
|
217
|
-
this.expressRouter.use(c.root, c.expressRouter)
|
|
218
|
-
})
|
|
219
|
-
}
|
|
220
|
-
if (this.routes.length) {
|
|
221
|
-
this.routes.forEach(r => {
|
|
222
|
-
Object.entries(r.handlers).forEach(([method, handler]) => {
|
|
223
|
-
this.expressRouter[method](r.route, ServerUtils.cacheRouteConfig(r), ...this.getHandlerMiddleware(), handler)
|
|
224
|
-
this.log('debug', 'ADD_ROUTE', method.toUpperCase(), `${this.path !== '/' ? this.path : ''}${r.route}`)
|
|
225
|
-
})
|
|
226
|
-
})
|
|
227
|
-
}
|
|
228
|
-
// add to the parent stack
|
|
229
|
-
if (this.parentRouter instanceof Router) {
|
|
230
|
-
this.parentRouter.expressRouter.use(`/${this.root}`, this.expressRouter)
|
|
231
|
-
} else {
|
|
232
|
-
const route = this.root[0] !== '/' ? `/${this.root}` : this.root
|
|
233
|
-
this.parentRouter.use(route, this.expressRouter)
|
|
234
|
-
}
|
|
235
|
-
this._initialised = true
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* Shortcut for checking Router has initialised, logging a warning if not
|
|
240
|
-
* @param {String} message Message to log on error
|
|
241
|
-
* @return {Boolean}
|
|
242
|
-
*/
|
|
243
|
-
warnOnInited (message) {
|
|
244
|
-
if (this._initialised) {
|
|
245
|
-
this.log('warn', `router has already initialised, ${message}`)
|
|
246
|
-
}
|
|
247
|
-
return this._initialised
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Creates an array defining the router inheritance hierarchy
|
|
252
|
-
* @param {Router} router The root router
|
|
253
|
-
* @return {Array}
|
|
254
|
-
*/
|
|
255
|
-
flattenRouters (router = this) {
|
|
256
|
-
return router.childRouters.reduce((a, c) => {
|
|
257
|
-
c.childRouters ? a.push(...this.flattenRouters(c)) : a.push(c)
|
|
258
|
-
return a
|
|
259
|
-
}, [router])
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Logs a message
|
|
264
|
-
* @param {String} level Level of log
|
|
265
|
-
* @param {...*} args Arguments to be logged
|
|
266
|
-
*/
|
|
267
|
-
log (level, ...args) {
|
|
268
|
-
App.instance.logger.log(level, this.constructor.name.toLowerCase(), ...args)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export default Router
|
|
1
|
+
import _ from 'lodash'
|
|
2
|
+
import { App } from 'adapt-authoring-core'
|
|
3
|
+
import express from 'express'
|
|
4
|
+
import ServerUtils from './ServerUtils.js'
|
|
5
|
+
/**
|
|
6
|
+
* Handles the Express routing functionality
|
|
7
|
+
* @memberof server
|
|
8
|
+
*/
|
|
9
|
+
class Router {
|
|
10
|
+
/**
|
|
11
|
+
* If passing an {@link ExpressRouter} as the parentRouter, it is assumed that the Express Router is the top of the router 'heirarchy' (which will have an impact of some of the {@link Router} methods)
|
|
12
|
+
* @param {String} root Route API endpoint for this router
|
|
13
|
+
* @param {Router|ExpressRouter} parentRouter Parent to mount router
|
|
14
|
+
* @param {Array<Route>} routes Array of routes
|
|
15
|
+
*/
|
|
16
|
+
constructor (root, parentRouter, routes) {
|
|
17
|
+
/**
|
|
18
|
+
* The root route the router will be mounted at
|
|
19
|
+
* @type {String}
|
|
20
|
+
*/
|
|
21
|
+
this.root = root
|
|
22
|
+
/**
|
|
23
|
+
* Routes config
|
|
24
|
+
* @type {Array<Route>}
|
|
25
|
+
*/
|
|
26
|
+
this.routes = routes ?? []
|
|
27
|
+
/**
|
|
28
|
+
* Express router instance
|
|
29
|
+
* @type {external:ExpressRouter}
|
|
30
|
+
*/
|
|
31
|
+
this.expressRouter = express.Router()
|
|
32
|
+
/**
|
|
33
|
+
* Express router instance
|
|
34
|
+
* @type {ExpressApp|Router}
|
|
35
|
+
*/
|
|
36
|
+
this.parentRouter = parentRouter
|
|
37
|
+
/**
|
|
38
|
+
* List of sub-routers
|
|
39
|
+
* @type {Array<Router>}
|
|
40
|
+
*/
|
|
41
|
+
this.childRouters = []
|
|
42
|
+
/**
|
|
43
|
+
* Middleware stack to be added directly to the router
|
|
44
|
+
* @type {Array<Function>}
|
|
45
|
+
*/
|
|
46
|
+
this.routerMiddleware = [
|
|
47
|
+
ServerUtils.addErrorHandler
|
|
48
|
+
]
|
|
49
|
+
/**
|
|
50
|
+
* Middleware stack to be added before route handlers (useful if you need access to specific request attributes that don't exist when standard middleware runs)
|
|
51
|
+
* @type {Array<Function>}
|
|
52
|
+
*/
|
|
53
|
+
this.handlerMiddleware = [
|
|
54
|
+
ServerUtils.addExistenceProps,
|
|
55
|
+
ServerUtils.handleInternalRoutes
|
|
56
|
+
]
|
|
57
|
+
/** @ignore */this._initialised = false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns the map of routes attached to this router
|
|
62
|
+
* @type {Object}
|
|
63
|
+
*/
|
|
64
|
+
get map () {
|
|
65
|
+
return ServerUtils.generateRouterMap(this)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Generates this router's path from its ancestors
|
|
70
|
+
* @type {String}
|
|
71
|
+
*/
|
|
72
|
+
get path () {
|
|
73
|
+
let p = ''
|
|
74
|
+
|
|
75
|
+
if (_.isString(this.parentRouter.path)) {
|
|
76
|
+
p += this.parentRouter.path
|
|
77
|
+
}
|
|
78
|
+
if (p[p.length - 1] !== '/' && this.root[0] !== '/') {
|
|
79
|
+
p += '/'
|
|
80
|
+
}
|
|
81
|
+
return p + this.root
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Returns the URL for the router
|
|
86
|
+
* @return {String} The URL
|
|
87
|
+
*/
|
|
88
|
+
get url () {
|
|
89
|
+
try {
|
|
90
|
+
const serverUrl = App.instance.dependencyloader.instances['adapt-authoring-server'].url
|
|
91
|
+
return serverUrl + this.path
|
|
92
|
+
} catch (e) {
|
|
93
|
+
this.log('error', e)
|
|
94
|
+
return ''
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Adds middleware to the router stack. Accepts multiple params.
|
|
100
|
+
* @param {...Function} func Middleware function(s) to be added
|
|
101
|
+
* @return {AbstractApiModule} This instance, for chaining
|
|
102
|
+
* @see https://expressjs.com/en/guide/using-middleware.html
|
|
103
|
+
*/
|
|
104
|
+
addMiddleware (...func) {
|
|
105
|
+
return this._addMiddleware(this.routerMiddleware, ...func)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Adds middleware to be called prior to any route handlers. Accepts multiple params. Useful if you need access to specific request attributes that don't exist when standard middleware runs.
|
|
110
|
+
* @param {...Function} func Middleware function(s) to be added
|
|
111
|
+
* @return {AbstractApiModule} This instance, for chaining
|
|
112
|
+
* @see https://expressjs.com/en/guide/using-middleware.html
|
|
113
|
+
*/
|
|
114
|
+
addHandlerMiddleware (...func) {
|
|
115
|
+
return this._addMiddleware(this.handlerMiddleware, ...func)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** @ignore */ _addMiddleware (stack, ...func) {
|
|
119
|
+
if (func.length) {
|
|
120
|
+
this.warnOnInited('middleware may not be called before any route handlers')
|
|
121
|
+
func.forEach(f => _.isFunction(f) && !stack.includes(f) && stack.push(f))
|
|
122
|
+
}
|
|
123
|
+
return this
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Recursively gets middleware of the current router heirarchy
|
|
128
|
+
* @param {Router} router The current router (used when run recursively)
|
|
129
|
+
* @param {Array<function>} middleware Middleware function(s) (used when run recursively)
|
|
130
|
+
* @return {Array<Function>}
|
|
131
|
+
*/
|
|
132
|
+
getHandlerMiddleware (router = this, middleware = []) {
|
|
133
|
+
if (!(router instanceof Router)) {
|
|
134
|
+
return middleware
|
|
135
|
+
}
|
|
136
|
+
return _.uniq(this.getHandlerMiddleware(router.parentRouter, [...router.handlerMiddleware, ...middleware]))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Store route definition. Accepts multiple params.
|
|
141
|
+
* @param {...Route} route Config of route(s) to be added
|
|
142
|
+
* @return {AbstractApiModule} This instance, for chaining
|
|
143
|
+
*/
|
|
144
|
+
addRoute (...route) {
|
|
145
|
+
const inited = this.warnOnInited(`cannot set further routes (${this.path} ${route.map(r => r.route).join(', ')})`)
|
|
146
|
+
if (!inited && route.length) {
|
|
147
|
+
this.routes.push(...route.filter(this.validateRoute, this))
|
|
148
|
+
}
|
|
149
|
+
return this
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Function for filtering bad route configs
|
|
154
|
+
* @param {Route} r Route config
|
|
155
|
+
* @return {Boolean}
|
|
156
|
+
*/
|
|
157
|
+
validateRoute (r) {
|
|
158
|
+
const ePrefix = `invalid route config for ${this.route} router`
|
|
159
|
+
if (!_.isString(r.route)) {
|
|
160
|
+
this.log('warn', `${ePrefix}, route must be a string`)
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
if (!r.handlers) {
|
|
164
|
+
this.log('warn', `${ePrefix}, no route handlers defined`)
|
|
165
|
+
return false
|
|
166
|
+
}
|
|
167
|
+
// handlers can be single function or array of functions
|
|
168
|
+
const allHandlersFuncs = Object.entries(r.handlers).every(([m, h]) => {
|
|
169
|
+
if (this.expressRouter[m] === undefined) {
|
|
170
|
+
this.log('warn', `${ePrefix}, ${m} must be a valid Express.js function`)
|
|
171
|
+
return false
|
|
172
|
+
}
|
|
173
|
+
if (!_.isFunction(h) && !(_.isArray(h) && h.every(_.isFunction))) {
|
|
174
|
+
this.log('warn', `${ePrefix} ${m.toUpperCase()} ${r.route}, all route handlers must be functions`)
|
|
175
|
+
return false
|
|
176
|
+
}
|
|
177
|
+
return true
|
|
178
|
+
})
|
|
179
|
+
if (!allHandlersFuncs) {
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
return true
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates and adds a sub-router to this router.
|
|
187
|
+
* @param {string} root The root of the child router
|
|
188
|
+
* @param {Array<Route>} routes Array of Routes to add
|
|
189
|
+
* @return {Router} The new router instance
|
|
190
|
+
*/
|
|
191
|
+
createChildRouter (root, routes) {
|
|
192
|
+
if (this.warnOnInited(`cannot create further child routers (${this.path}/${root})`)) {
|
|
193
|
+
return this
|
|
194
|
+
}
|
|
195
|
+
const router = new Router(root, this, routes)
|
|
196
|
+
|
|
197
|
+
this.childRouters.push(router)
|
|
198
|
+
|
|
199
|
+
this.log('debug', 'ADD_ROUTER', router.path)
|
|
200
|
+
|
|
201
|
+
return router
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Initialises the API
|
|
206
|
+
*/
|
|
207
|
+
init () {
|
|
208
|
+
if (this.warnOnInited(`(${this.path})`)) {
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
if (this.routerMiddleware.length) {
|
|
212
|
+
this.expressRouter.use(...this.routerMiddleware)
|
|
213
|
+
}
|
|
214
|
+
if (this.childRouters.length) {
|
|
215
|
+
this.childRouters.forEach(c => {
|
|
216
|
+
c.init()
|
|
217
|
+
this.expressRouter.use(c.root, c.expressRouter)
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
if (this.routes.length) {
|
|
221
|
+
this.routes.forEach(r => {
|
|
222
|
+
Object.entries(r.handlers).forEach(([method, handler]) => {
|
|
223
|
+
this.expressRouter[method](r.route, ServerUtils.cacheRouteConfig(r), ...this.getHandlerMiddleware(), handler)
|
|
224
|
+
this.log('debug', 'ADD_ROUTE', method.toUpperCase(), `${this.path !== '/' ? this.path : ''}${r.route}`)
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
// add to the parent stack
|
|
229
|
+
if (this.parentRouter instanceof Router) {
|
|
230
|
+
this.parentRouter.expressRouter.use(`/${this.root}`, this.expressRouter)
|
|
231
|
+
} else {
|
|
232
|
+
const route = this.root[0] !== '/' ? `/${this.root}` : this.root
|
|
233
|
+
this.parentRouter.use(route, this.expressRouter)
|
|
234
|
+
}
|
|
235
|
+
this._initialised = true
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Shortcut for checking Router has initialised, logging a warning if not
|
|
240
|
+
* @param {String} message Message to log on error
|
|
241
|
+
* @return {Boolean}
|
|
242
|
+
*/
|
|
243
|
+
warnOnInited (message) {
|
|
244
|
+
if (this._initialised) {
|
|
245
|
+
this.log('warn', `router has already initialised, ${message}`)
|
|
246
|
+
}
|
|
247
|
+
return this._initialised
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Creates an array defining the router inheritance hierarchy
|
|
252
|
+
* @param {Router} router The root router
|
|
253
|
+
* @return {Array}
|
|
254
|
+
*/
|
|
255
|
+
flattenRouters (router = this) {
|
|
256
|
+
return router.childRouters.reduce((a, c) => {
|
|
257
|
+
c.childRouters ? a.push(...this.flattenRouters(c)) : a.push(c)
|
|
258
|
+
return a
|
|
259
|
+
}, [router])
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Logs a message
|
|
264
|
+
* @param {String} level Level of log
|
|
265
|
+
* @param {...*} args Arguments to be logged
|
|
266
|
+
*/
|
|
267
|
+
log (level, ...args) {
|
|
268
|
+
App.instance.logger.log(level, this.constructor.name.toLowerCase(), ...args)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export default Router
|