@jcbuisson/express-x 2.1.1 → 2.1.4
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/package.json +1 -1
- package/src/common-hooks.mjs +17 -12
- package/src/index.mjs +2 -1
- package/src/server.mjs +43 -18
package/package.json
CHANGED
package/src/common-hooks.mjs
CHANGED
|
@@ -35,25 +35,30 @@ export function protect(field) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
/*
|
|
38
|
-
*
|
|
39
|
-
* Check if the 'expireAt' key in socket.data is met
|
|
40
|
-
* If it is met, throw an error (which will be sent back to the calling server or client) and reset socket.data
|
|
41
|
-
* If not, do nothing. If needed, an application-level hook may automatically extend the expiration data at each service call
|
|
38
|
+
* Throw an error for a client service method call when socket.data.expiresAt is missing or overdue
|
|
42
39
|
*/
|
|
43
40
|
export const isNotExpired = async (context) => {
|
|
44
|
-
if
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
const
|
|
41
|
+
// do nothing if it's not a client call from a ws connexion
|
|
42
|
+
if (!context.socket) return
|
|
43
|
+
const expiresAt = context.socket.data.expiresAt
|
|
44
|
+
if (expiresAt) {
|
|
45
|
+
const expiresAtDate = new Date(expiresAt)
|
|
49
46
|
const now = new Date()
|
|
50
|
-
if (now >
|
|
47
|
+
if (now > expiresAtDate) {
|
|
51
48
|
// expiration date is met: clear socket.data & throw exception
|
|
52
|
-
|
|
53
|
-
socket.data = { clientIP }
|
|
49
|
+
context.socket.data = {}
|
|
54
50
|
throw new Error('session-expired')
|
|
55
51
|
}
|
|
56
52
|
} else {
|
|
57
53
|
throw new Error('session-expired')
|
|
58
54
|
}
|
|
59
55
|
}
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* Throw an error for a client service method call when socket.data does not contain user
|
|
59
|
+
*/
|
|
60
|
+
export const isAuthenticated = async (context) => {
|
|
61
|
+
// do nothing if it's not a client call from a ws connexion
|
|
62
|
+
if (!context.socket) return
|
|
63
|
+
if (!context.socket.data.user) throw new Error('not-authenticated')
|
|
64
|
+
}
|
package/src/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { expressX } from './server.mjs'
|
|
3
|
-
import { addTimestamp, hashPassword, protect, isNotExpired } from './common-hooks.mjs'
|
|
3
|
+
import { addTimestamp, hashPassword, protect, isAuthenticated, isNotExpired } from './common-hooks.mjs'
|
|
4
4
|
|
|
5
5
|
export {
|
|
6
6
|
expressX,
|
|
@@ -8,5 +8,6 @@ export {
|
|
|
8
8
|
addTimestamp,
|
|
9
9
|
hashPassword,
|
|
10
10
|
protect,
|
|
11
|
+
isAuthenticated,
|
|
11
12
|
isNotExpired,
|
|
12
13
|
}
|
package/src/server.mjs
CHANGED
|
@@ -3,14 +3,27 @@ import { createServer } from "http"
|
|
|
3
3
|
import { Server } from "socket.io"
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
// UTILISER L'ACKNOWLEDGEMENT : https://socket.io/docs/v4/#acknowledgements
|
|
7
|
+
|
|
6
8
|
export function expressX(config) {
|
|
7
9
|
|
|
8
10
|
const services = {}
|
|
9
11
|
let appHooks = []
|
|
10
|
-
|
|
12
|
+
const socketConnectListeners = []
|
|
13
|
+
const socketDisconnectingListeners = []
|
|
14
|
+
const socketDisconnectListeners = []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
function addConnectListener(func) {
|
|
18
|
+
socketConnectListeners.push(func)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function addDisconnectingListener(func) {
|
|
22
|
+
socketDisconnectingListeners.push(func)
|
|
23
|
+
}
|
|
11
24
|
|
|
12
|
-
function
|
|
13
|
-
|
|
25
|
+
function addDisconnectListener(func) {
|
|
26
|
+
socketDisconnectListeners.push(func)
|
|
14
27
|
}
|
|
15
28
|
|
|
16
29
|
const app = express()
|
|
@@ -29,6 +42,9 @@ export function expressX(config) {
|
|
|
29
42
|
}
|
|
30
43
|
})
|
|
31
44
|
|
|
45
|
+
// so that io server is accessible to hooks & services
|
|
46
|
+
app.set('io', io)
|
|
47
|
+
|
|
32
48
|
// logging function - a winston logger must be configured first
|
|
33
49
|
app.log = (severity, message) => {
|
|
34
50
|
const logger = app.get('logger')
|
|
@@ -43,21 +59,26 @@ export function expressX(config) {
|
|
|
43
59
|
} else {
|
|
44
60
|
// new or unrecoverable connection
|
|
45
61
|
// (page open, page refresh/reload)
|
|
46
|
-
socket.data.clientIP = socket.handshake.address
|
|
47
62
|
}
|
|
48
63
|
|
|
49
64
|
app.log('verbose', `Client connected ${socket.id}`)
|
|
50
65
|
|
|
51
|
-
// emit 'connection' event for app (expressjs extends EventEmitter)
|
|
52
|
-
app.emit('connection', socket)
|
|
66
|
+
// // emit 'connection' event for app (expressjs extends EventEmitter)
|
|
67
|
+
// app.emit('connection', socket)
|
|
68
|
+
|
|
69
|
+
socketConnectListeners.forEach(listener => listener(socket))
|
|
53
70
|
|
|
54
|
-
|
|
71
|
+
// // send 'connected' event to client
|
|
72
|
+
// socket.emit('connected', socket.id)
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
socket.on('disconnecting', (reason) => {
|
|
75
|
+
app.log('verbose', `Client disconnecting ${socket.id}, ${reason}`)
|
|
76
|
+
socketDisconnectingListeners.forEach(listener => listener(socket, reason))
|
|
77
|
+
})
|
|
58
78
|
|
|
59
|
-
socket.on('disconnect', () => {
|
|
60
|
-
app.log('verbose', `Client
|
|
79
|
+
socket.on('disconnect', (reason) => {
|
|
80
|
+
app.log('verbose', `Client disconnect ${socket.id}, ${reason}`)
|
|
81
|
+
socketDisconnectListeners.forEach(listener => listener(socket, reason))
|
|
61
82
|
})
|
|
62
83
|
|
|
63
84
|
/*
|
|
@@ -94,13 +115,14 @@ export function expressX(config) {
|
|
|
94
115
|
result,
|
|
95
116
|
})
|
|
96
117
|
} catch(err) {
|
|
97
|
-
console.log('!!!!!!error', err
|
|
118
|
+
console.log('!!!!!!error', err)
|
|
98
119
|
app.log('verbose', err.stack)
|
|
99
120
|
socket.emit('client-response', {
|
|
100
121
|
uid,
|
|
101
122
|
error: {
|
|
102
123
|
code: err.code || 'unknown-error',
|
|
103
|
-
message: err.
|
|
124
|
+
message: err.message,
|
|
125
|
+
stack: err.stack,
|
|
104
126
|
}
|
|
105
127
|
})
|
|
106
128
|
}
|
|
@@ -120,8 +142,9 @@ export function expressX(config) {
|
|
|
120
142
|
uid,
|
|
121
143
|
error: {
|
|
122
144
|
code: err.code || 'unknown-error',
|
|
123
|
-
message: err.
|
|
124
|
-
|
|
145
|
+
message: err.message,
|
|
146
|
+
stack: err.stack,
|
|
147
|
+
}
|
|
125
148
|
})
|
|
126
149
|
}
|
|
127
150
|
} else {
|
|
@@ -153,8 +176,8 @@ export function expressX(config) {
|
|
|
153
176
|
// put args into context
|
|
154
177
|
context.args = args
|
|
155
178
|
|
|
156
|
-
// if a hook or the method throws an error, it will be caught by `socket.on('client-request'`
|
|
157
|
-
//
|
|
179
|
+
// if a hook or the method throws an error, it will be caught by `socket.on('client-request'`
|
|
180
|
+
// and the client will get a rejected promise
|
|
158
181
|
|
|
159
182
|
// call 'before' hooks, possibly modifying `context`
|
|
160
183
|
const beforeAppHooks = appHooks?.before || []
|
|
@@ -271,7 +294,9 @@ export function expressX(config) {
|
|
|
271
294
|
joinChannel,
|
|
272
295
|
leaveChannel,
|
|
273
296
|
sendAppEvent,
|
|
274
|
-
|
|
297
|
+
addConnectListener,
|
|
298
|
+
addDisconnectingListener,
|
|
299
|
+
addDisconnectListener,
|
|
275
300
|
})
|
|
276
301
|
|
|
277
302
|
}
|