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/ServerModule.js
CHANGED
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
import express from 'express'
|
|
2
|
-
import { AbstractModule, Hook } from 'adapt-authoring-core'
|
|
3
|
-
import Router from './Router.js'
|
|
4
|
-
import ServerUtils from './ServerUtils.js'
|
|
5
|
-
/**
|
|
6
|
-
* Adds an Express server to the authoring tool
|
|
7
|
-
* @memberof server
|
|
8
|
-
* @extends {AbstractModule}
|
|
9
|
-
*/
|
|
10
|
-
class ServerModule extends AbstractModule {
|
|
11
|
-
/** @override */
|
|
12
|
-
async init () {
|
|
13
|
-
/**
|
|
14
|
-
* The main Express Application
|
|
15
|
-
* @type {external:ExpressApp}
|
|
16
|
-
*/
|
|
17
|
-
this.expressApp = express()
|
|
18
|
-
/**
|
|
19
|
-
* The default/'root' router for the application
|
|
20
|
-
* @type {Router}
|
|
21
|
-
*/
|
|
22
|
-
this.root = new Router('/', this.expressApp)
|
|
23
|
-
/**
|
|
24
|
-
* The router which handles all APIs
|
|
25
|
-
* @type {Router}
|
|
26
|
-
*/
|
|
27
|
-
this.api = new Router('api', this.root)
|
|
28
|
-
/**
|
|
29
|
-
* Whether the HTTP server is listening for requests
|
|
30
|
-
* @type {Boolean}
|
|
31
|
-
*/
|
|
32
|
-
this.isListening = false
|
|
33
|
-
/**
|
|
34
|
-
* Hook invoked when the HTTP server is listening
|
|
35
|
-
* @type {Hook}
|
|
36
|
-
*/
|
|
37
|
-
this.listeningHook = new Hook()
|
|
38
|
-
/**
|
|
39
|
-
* Hook for interrupting requests
|
|
40
|
-
* @type {Hook}
|
|
41
|
-
*/
|
|
42
|
-
this.requestHook = new Hook({ mutable: true })
|
|
43
|
-
/**
|
|
44
|
-
* Reference to the HTTP server used by Express
|
|
45
|
-
* @type {external:HttpServer}
|
|
46
|
-
*/
|
|
47
|
-
this.httpServer = undefined
|
|
48
|
-
|
|
49
|
-
this.expressApp.set('trust proxy', this.getConfig('trustProxy'))
|
|
50
|
-
this.expressApp.set('view engine', 'hbs')
|
|
51
|
-
/**
|
|
52
|
-
* Need to wait for other modules to load before we properly initialise &
|
|
53
|
-
* start listening for incoming connections
|
|
54
|
-
*/
|
|
55
|
-
this.app.onReady().then(this.start.bind(this)).catch(e => this.log('error', e))
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Starts the HTTP server
|
|
60
|
-
*/
|
|
61
|
-
async start () {
|
|
62
|
-
// Initialise the root router
|
|
63
|
-
this.root.init()
|
|
64
|
-
// Initialise the API router
|
|
65
|
-
this.api.expressRouter.get('/', ServerUtils.mapHandler(this.api).bind(this))
|
|
66
|
-
this.api.addMiddleware(
|
|
67
|
-
ServerUtils.debugRequestTime
|
|
68
|
-
)
|
|
69
|
-
this.api.init()
|
|
70
|
-
// add not-found handlers
|
|
71
|
-
this.api.expressRouter.use(ServerUtils.apiNotFoundHandler.bind(this))
|
|
72
|
-
this.root.expressRouter.use(ServerUtils.rootNotFoundHandler.bind(this))
|
|
73
|
-
// add generic error handling
|
|
74
|
-
this.expressApp.use(ServerUtils.genericErrorHandler.bind(this))
|
|
75
|
-
|
|
76
|
-
await this.listen()
|
|
77
|
-
this.log('info', `listening on ${this.port}`)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Server hostname
|
|
82
|
-
* @type {String}
|
|
83
|
-
*/
|
|
84
|
-
get host () {
|
|
85
|
-
return this.getConfig('host')
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Port the app should listen on
|
|
90
|
-
* @type {String}
|
|
91
|
-
*/
|
|
92
|
-
get port () {
|
|
93
|
-
return this.getConfig('port')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* The URL for the server from its config
|
|
98
|
-
* @type {String}
|
|
99
|
-
*/
|
|
100
|
-
get url () {
|
|
101
|
-
return this.getConfig('url') || `${this.getConfig('host')}:${this.port}`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Middleware function to allow serving of static files
|
|
106
|
-
* @see https://expressjs.com/en/4x/api.html#express.static
|
|
107
|
-
* @param {String} root The root directory from which to serve static assets
|
|
108
|
-
* @param {Object} options Options to pass to the function
|
|
109
|
-
* @return {Function}
|
|
110
|
-
*/
|
|
111
|
-
static (root, options) {
|
|
112
|
-
return express.static(root, options)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Start the Express server (shortcut to the Express function of the same name).
|
|
117
|
-
* @see https://expressjs.com/en/4x/api.html#app.listen
|
|
118
|
-
* @param {function} func Callback function to be called on connection.
|
|
119
|
-
* @return {Promise} Resolves with the server instance
|
|
120
|
-
*/
|
|
121
|
-
listen () {
|
|
122
|
-
return new Promise((resolve, reject) => {
|
|
123
|
-
this.httpServer = this.expressApp.listen(this.port, this.host, () => {
|
|
124
|
-
this.isListening = true
|
|
125
|
-
this.listeningHook.invoke()
|
|
126
|
-
resolve(this.httpServer)
|
|
127
|
-
}).once('error', e => reject(this.app.errors.SERVER_START.setData({ error: e })))
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Stops the Express server
|
|
133
|
-
* @return {Promise}
|
|
134
|
-
*/
|
|
135
|
-
close () {
|
|
136
|
-
return new Promise((resolve, reject) => {
|
|
137
|
-
if (!this.httpServer) {
|
|
138
|
-
this.log('warn', 'cannot stop server, it wasn\'t running!')
|
|
139
|
-
return resolve()
|
|
140
|
-
}
|
|
141
|
-
if (!this.isListening) return this.listeningHook.tap(this.close.bind(this))
|
|
142
|
-
else this.listeningHook.untap(this.close)
|
|
143
|
-
|
|
144
|
-
this.httpServer.close(() => {
|
|
145
|
-
this.httpServer = undefined
|
|
146
|
-
this.log('info', `no longer listening on ${this.port}`)
|
|
147
|
-
return resolve()
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export default ServerModule
|
|
1
|
+
import express from 'express'
|
|
2
|
+
import { AbstractModule, Hook } from 'adapt-authoring-core'
|
|
3
|
+
import Router from './Router.js'
|
|
4
|
+
import ServerUtils from './ServerUtils.js'
|
|
5
|
+
/**
|
|
6
|
+
* Adds an Express server to the authoring tool
|
|
7
|
+
* @memberof server
|
|
8
|
+
* @extends {AbstractModule}
|
|
9
|
+
*/
|
|
10
|
+
class ServerModule extends AbstractModule {
|
|
11
|
+
/** @override */
|
|
12
|
+
async init () {
|
|
13
|
+
/**
|
|
14
|
+
* The main Express Application
|
|
15
|
+
* @type {external:ExpressApp}
|
|
16
|
+
*/
|
|
17
|
+
this.expressApp = express()
|
|
18
|
+
/**
|
|
19
|
+
* The default/'root' router for the application
|
|
20
|
+
* @type {Router}
|
|
21
|
+
*/
|
|
22
|
+
this.root = new Router('/', this.expressApp)
|
|
23
|
+
/**
|
|
24
|
+
* The router which handles all APIs
|
|
25
|
+
* @type {Router}
|
|
26
|
+
*/
|
|
27
|
+
this.api = new Router('api', this.root)
|
|
28
|
+
/**
|
|
29
|
+
* Whether the HTTP server is listening for requests
|
|
30
|
+
* @type {Boolean}
|
|
31
|
+
*/
|
|
32
|
+
this.isListening = false
|
|
33
|
+
/**
|
|
34
|
+
* Hook invoked when the HTTP server is listening
|
|
35
|
+
* @type {Hook}
|
|
36
|
+
*/
|
|
37
|
+
this.listeningHook = new Hook()
|
|
38
|
+
/**
|
|
39
|
+
* Hook for interrupting requests
|
|
40
|
+
* @type {Hook}
|
|
41
|
+
*/
|
|
42
|
+
this.requestHook = new Hook({ mutable: true })
|
|
43
|
+
/**
|
|
44
|
+
* Reference to the HTTP server used by Express
|
|
45
|
+
* @type {external:HttpServer}
|
|
46
|
+
*/
|
|
47
|
+
this.httpServer = undefined
|
|
48
|
+
|
|
49
|
+
this.expressApp.set('trust proxy', this.getConfig('trustProxy'))
|
|
50
|
+
this.expressApp.set('view engine', 'hbs')
|
|
51
|
+
/**
|
|
52
|
+
* Need to wait for other modules to load before we properly initialise &
|
|
53
|
+
* start listening for incoming connections
|
|
54
|
+
*/
|
|
55
|
+
this.app.onReady().then(this.start.bind(this)).catch(e => this.log('error', e))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Starts the HTTP server
|
|
60
|
+
*/
|
|
61
|
+
async start () {
|
|
62
|
+
// Initialise the root router
|
|
63
|
+
this.root.init()
|
|
64
|
+
// Initialise the API router
|
|
65
|
+
this.api.expressRouter.get('/', ServerUtils.mapHandler(this.api).bind(this))
|
|
66
|
+
this.api.addMiddleware(
|
|
67
|
+
ServerUtils.debugRequestTime
|
|
68
|
+
)
|
|
69
|
+
this.api.init()
|
|
70
|
+
// add not-found handlers
|
|
71
|
+
this.api.expressRouter.use(ServerUtils.apiNotFoundHandler.bind(this))
|
|
72
|
+
this.root.expressRouter.use(ServerUtils.rootNotFoundHandler.bind(this))
|
|
73
|
+
// add generic error handling
|
|
74
|
+
this.expressApp.use(ServerUtils.genericErrorHandler.bind(this))
|
|
75
|
+
|
|
76
|
+
await this.listen()
|
|
77
|
+
this.log('info', `listening on ${this.port}`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Server hostname
|
|
82
|
+
* @type {String}
|
|
83
|
+
*/
|
|
84
|
+
get host () {
|
|
85
|
+
return this.getConfig('host')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Port the app should listen on
|
|
90
|
+
* @type {String}
|
|
91
|
+
*/
|
|
92
|
+
get port () {
|
|
93
|
+
return this.getConfig('port')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* The URL for the server from its config
|
|
98
|
+
* @type {String}
|
|
99
|
+
*/
|
|
100
|
+
get url () {
|
|
101
|
+
return this.getConfig('url') || `${this.getConfig('host')}:${this.port}`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Middleware function to allow serving of static files
|
|
106
|
+
* @see https://expressjs.com/en/4x/api.html#express.static
|
|
107
|
+
* @param {String} root The root directory from which to serve static assets
|
|
108
|
+
* @param {Object} options Options to pass to the function
|
|
109
|
+
* @return {Function}
|
|
110
|
+
*/
|
|
111
|
+
static (root, options) {
|
|
112
|
+
return express.static(root, options)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Start the Express server (shortcut to the Express function of the same name).
|
|
117
|
+
* @see https://expressjs.com/en/4x/api.html#app.listen
|
|
118
|
+
* @param {function} func Callback function to be called on connection.
|
|
119
|
+
* @return {Promise} Resolves with the server instance
|
|
120
|
+
*/
|
|
121
|
+
listen () {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
this.httpServer = this.expressApp.listen(this.port, this.host, () => {
|
|
124
|
+
this.isListening = true
|
|
125
|
+
this.listeningHook.invoke()
|
|
126
|
+
resolve(this.httpServer)
|
|
127
|
+
}).once('error', e => reject(this.app.errors.SERVER_START.setData({ error: e })))
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Stops the Express server
|
|
133
|
+
* @return {Promise}
|
|
134
|
+
*/
|
|
135
|
+
close () {
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
if (!this.httpServer) {
|
|
138
|
+
this.log('warn', 'cannot stop server, it wasn\'t running!')
|
|
139
|
+
return resolve()
|
|
140
|
+
}
|
|
141
|
+
if (!this.isListening) return this.listeningHook.tap(this.close.bind(this))
|
|
142
|
+
else this.listeningHook.untap(this.close)
|
|
143
|
+
|
|
144
|
+
this.httpServer.close(() => {
|
|
145
|
+
this.httpServer = undefined
|
|
146
|
+
this.log('info', `no longer listening on ${this.port}`)
|
|
147
|
+
return resolve()
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default ServerModule
|