@jcbuisson/express-x 1.4.3 → 1.5.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/package.json +1 -1
- package/src/index.mjs +1 -2
- package/src/server.mjs +73 -37
package/package.json
CHANGED
package/src/index.mjs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import { expressX } from './server.mjs'
|
|
3
|
-
import { hashPassword, protect,
|
|
3
|
+
import { hashPassword, protect, } from './common-hooks.mjs'
|
|
4
4
|
|
|
5
5
|
export {
|
|
6
6
|
expressX,
|
|
7
7
|
|
|
8
8
|
hashPassword,
|
|
9
9
|
protect,
|
|
10
|
-
setSessionJWT,
|
|
11
10
|
}
|
package/src/server.mjs
CHANGED
|
@@ -15,15 +15,64 @@ export function expressX(prisma, options = {}) {
|
|
|
15
15
|
|
|
16
16
|
const services = {}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
let lastConnectionId = options.initialConnectionId || 1
|
|
20
|
-
// TODO: use redis to store `connections` and `lastConnectionId` for a clustered deployment
|
|
21
|
-
// (a connection/reconnection may occur on two different servers)
|
|
18
|
+
const cnx2Socket = {}
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
function createConnection() {
|
|
21
|
+
return app.service('Connection').create({})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function deleteConnection(id) {
|
|
25
|
+
try {
|
|
26
|
+
await app.service('Connection')._delete({ where: { id }})
|
|
27
|
+
} catch(err) {
|
|
28
|
+
console.log('111')
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getConnection(id) {
|
|
33
|
+
return app.service('Connection').findUnique({ where: { id }})
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function copyConnection(id, connection) {
|
|
37
|
+
await app.service('Connection').update({
|
|
38
|
+
where: { id },
|
|
39
|
+
data: {
|
|
40
|
+
channelNames: connection.channelNames,
|
|
41
|
+
data: connection.data,
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function getChannelConnections(channelName) {
|
|
47
|
+
const connections = await app.service('Connection').findMany({})
|
|
48
|
+
return connections.filter(connection => {
|
|
49
|
+
const channelNames = JSON.parse(connection.channelNames)
|
|
50
|
+
return channelNames.includes(channelName)
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function addChannelToConnection(connection, channelName) {
|
|
55
|
+
const channelNames = JSON.parse(connection.channelNames)
|
|
56
|
+
if (!channelNames.includes(channelName)) channelNames.push(channelName)
|
|
57
|
+
await app.service('Connection').update({
|
|
58
|
+
where: { id: connection.id },
|
|
59
|
+
data: { channelNames: JSON.stringify(channelNames) },
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function removeChannelFromConnection(connection, channelName) {
|
|
64
|
+
const channelNames = JSON.parse(connection.channelNames).filter(name => name !== channelName)
|
|
65
|
+
await app.service('Connection').update({
|
|
66
|
+
where: { id },
|
|
67
|
+
data: { channelNames: JSON.stringify(channelNames) },
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
app.printCnx = async (label) => {
|
|
24
72
|
console.log(label)
|
|
25
|
-
|
|
26
|
-
|
|
73
|
+
const connections = await app.service('Connection').findMany({})
|
|
74
|
+
for (const connection of connections) {
|
|
75
|
+
console.log(`CNX ${connection.id}, data ${JSON.stringify(connection.data)}`)
|
|
27
76
|
}
|
|
28
77
|
}
|
|
29
78
|
|
|
@@ -257,18 +306,11 @@ export function expressX(prisma, options = {}) {
|
|
|
257
306
|
*/
|
|
258
307
|
const io = new Server(server)
|
|
259
308
|
|
|
260
|
-
io.on('connection', function(socket) {
|
|
261
|
-
const connection =
|
|
262
|
-
id: lastConnectionId++,
|
|
263
|
-
createdAt: new Date(),
|
|
264
|
-
socket,
|
|
265
|
-
channelNames: new Set(),
|
|
266
|
-
data: {},
|
|
267
|
-
}
|
|
309
|
+
io.on('connection', async function(socket) {
|
|
310
|
+
const connection = await createConnection()
|
|
268
311
|
app.log('verbose', `Client connected ${connection.id}`)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
// app.log('verbose', `Connection ids: ${Object.keys(app.connections)}`)
|
|
312
|
+
|
|
313
|
+
cnx2Socket[connection.id] = socket
|
|
272
314
|
|
|
273
315
|
// emit 'connection' event for app (expressjs extends EventEmitter)
|
|
274
316
|
app.emit('connection', connection)
|
|
@@ -282,32 +324,24 @@ export function expressX(prisma, options = {}) {
|
|
|
282
324
|
// remove connection record after 1mn (leaves time in case of connection transfer)
|
|
283
325
|
setTimeout(() => {
|
|
284
326
|
app.log('verbose', `Delete connection ${connection.id}`)
|
|
285
|
-
|
|
286
|
-
},
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
socket.on('reconnect', () => {
|
|
290
|
-
console.log('Client reconnected:', socket.id)
|
|
291
|
-
// Add your custom logic to link the reconnected WebSocket with the previous session
|
|
327
|
+
deleteConnection(connection.id)
|
|
328
|
+
}, 10 * 1000)
|
|
292
329
|
})
|
|
293
330
|
|
|
294
331
|
|
|
295
332
|
// handle connection data transfer caused by a disconnection/reconnection (page reload, network issue, etc.)
|
|
296
333
|
socket.on('cnx-transfer', async ({ from, to }) => {
|
|
297
334
|
app.log('verbose', `cnx-transfer from ${from} to ${to}`)
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
335
|
+
const fromConnection = await getConnection(from)
|
|
336
|
+
if (!fromConnection) return
|
|
337
|
+
await copyConnection(to, fromConnection)
|
|
338
|
+
cnx2Socket[to] = socket
|
|
339
|
+
await deleteConnection(from)
|
|
302
340
|
app.printCnx('AFTER TRANSFER')
|
|
303
341
|
// send acknowledge to client
|
|
304
342
|
io.emit('cnx-transfer-ack', to)
|
|
305
343
|
})
|
|
306
344
|
|
|
307
|
-
function wait(ms) {
|
|
308
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
309
|
-
}
|
|
310
|
-
|
|
311
345
|
/*
|
|
312
346
|
* Handle websocket client request
|
|
313
347
|
* Emit in return a 'client-response' message
|
|
@@ -371,10 +405,12 @@ export function expressX(prisma, options = {}) {
|
|
|
371
405
|
app.log('verbose', `publish channels ${service.name} ${action} ${channelNames}`)
|
|
372
406
|
for (const channelName of channelNames) {
|
|
373
407
|
app.log('verbose', `service-event ${service.name} ${action} ${channelName}`)
|
|
374
|
-
const connectionList = Object.values(app.connections).filter(cnx => cnx.channelNames.has(channelName))
|
|
408
|
+
// const connectionList = Object.values(app.connections).filter(cnx => cnx.channelNames.has(channelName))
|
|
409
|
+
const connectionList = getChannelConnections(channelName)
|
|
375
410
|
for (const connection of connectionList) {
|
|
376
411
|
app.log('verbose', `emit to ${connection.id} ${service.name} ${action} ${result}`)
|
|
377
|
-
connection.
|
|
412
|
+
const socket = cnx2Socket(connection.id)
|
|
413
|
+
socket.emit('service-event', {
|
|
378
414
|
name: service.name,
|
|
379
415
|
action,
|
|
380
416
|
result,
|
|
@@ -385,11 +421,11 @@ export function expressX(prisma, options = {}) {
|
|
|
385
421
|
}
|
|
386
422
|
|
|
387
423
|
function joinChannel(channelName, connection) {
|
|
388
|
-
connection
|
|
424
|
+
addChannelToConnection(connection, channelName)
|
|
389
425
|
}
|
|
390
426
|
|
|
391
427
|
function leaveChannel(channelName, connection) {
|
|
392
|
-
connection
|
|
428
|
+
removeChannelFromConnection(connection, channelName)
|
|
393
429
|
}
|
|
394
430
|
|
|
395
431
|
// enhance `app` with objects and methods
|