underpost 3.1.2 → 3.2.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/.env.example +0 -2
- package/.github/workflows/ghpkg.ci.yml +4 -4
- package/.github/workflows/npmpkg.ci.yml +38 -7
- package/.github/workflows/pwa-microservices-template-page.cd.yml +3 -4
- package/.github/workflows/pwa-microservices-template-test.ci.yml +3 -3
- package/.github/workflows/release.cd.yml +4 -4
- package/CHANGELOG.md +365 -1
- package/CLI-HELP.md +55 -3
- package/README.md +7 -3
- package/bin/build.js +18 -12
- package/bin/deploy.js +205 -225
- package/bin/file.js +3 -0
- package/conf.js +4 -10
- package/jsdoc.json +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
- package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +72 -50
- package/manifests/deployment/dd-test-development/proxy.yaml +13 -4
- package/manifests/deployment/playwright/deployment.yaml +1 -1
- package/nodemon.json +1 -1
- package/package.json +21 -14
- package/scripts/ports-ls.sh +2 -0
- package/scripts/rhel-grpc-setup.sh +56 -0
- package/src/api/file/file.ref.json +18 -0
- package/src/api/user/user.service.js +8 -7
- package/src/cli/cluster.js +7 -7
- package/src/cli/db.js +76 -242
- package/src/cli/deploy.js +104 -65
- package/src/cli/env.js +1 -0
- package/src/cli/fs.js +2 -1
- package/src/cli/index.js +50 -1
- package/src/cli/kubectl.js +211 -0
- package/src/cli/release.js +284 -0
- package/src/cli/repository.js +328 -112
- package/src/cli/run.js +283 -69
- package/src/cli/test.js +3 -3
- package/src/client/Default.index.js +3 -4
- package/src/client/components/core/Alert.js +2 -2
- package/src/client/components/core/AppStore.js +69 -0
- package/src/client/components/core/CalendarCore.js +2 -2
- package/src/client/components/core/Docs.js +9 -2
- package/src/client/components/core/DropDown.js +129 -17
- package/src/client/components/core/Keyboard.js +2 -2
- package/src/client/components/core/LogIn.js +2 -2
- package/src/client/components/core/LogOut.js +2 -2
- package/src/client/components/core/Modal.js +0 -1
- package/src/client/components/core/Panel.js +0 -1
- package/src/client/components/core/PanelForm.js +19 -19
- package/src/client/components/core/RichText.js +1 -2
- package/src/client/components/core/SocketIo.js +82 -29
- package/src/client/components/core/SocketIoHandler.js +75 -0
- package/src/client/components/core/Stream.js +143 -95
- package/src/client/components/core/Webhook.js +40 -7
- package/src/client/components/default/AppStoreDefault.js +5 -0
- package/src/client/components/default/LogInDefault.js +3 -3
- package/src/client/components/default/LogOutDefault.js +2 -2
- package/src/client/components/default/MenuDefault.js +5 -5
- package/src/client/components/default/SocketIoDefault.js +3 -51
- package/src/client/services/core/core.service.js +20 -8
- package/src/client/services/user/user.management.js +2 -2
- package/src/client/ssr/body/404.js +15 -11
- package/src/client/ssr/body/500.js +15 -11
- package/src/client/ssr/body/SwaggerDarkMode.js +285 -0
- package/src/client/ssr/offline/NoNetworkConnection.js +11 -10
- package/src/client/ssr/pages/Test.js +11 -10
- package/src/index.js +24 -1
- package/src/runtime/express/Express.js +26 -9
- package/src/runtime/lampp/Dockerfile +9 -2
- package/src/runtime/lampp/Lampp.js +4 -3
- package/src/runtime/wp/Dockerfile +64 -0
- package/src/runtime/wp/Wp.js +497 -0
- package/src/server/auth.js +30 -6
- package/src/server/backup.js +19 -1
- package/src/server/client-build-docs.js +51 -110
- package/src/server/client-build.js +55 -64
- package/src/server/client-formatted.js +109 -57
- package/src/server/conf.js +19 -15
- package/src/server/ipfs-client.js +24 -1
- package/src/server/peer.js +8 -0
- package/src/server/runtime.js +25 -1
- package/src/server/start.js +21 -8
- package/src/ws/IoInterface.js +1 -10
- package/src/ws/IoServer.js +14 -33
- package/src/ws/core/channels/core.ws.chat.js +65 -20
- package/src/ws/core/channels/core.ws.mailer.js +113 -32
- package/src/ws/core/channels/core.ws.stream.js +90 -31
- package/src/ws/core/core.ws.connection.js +12 -33
- package/src/ws/core/core.ws.emit.js +10 -26
- package/src/ws/core/core.ws.server.js +25 -58
- package/src/ws/default/channels/default.ws.main.js +53 -12
- package/src/ws/default/default.ws.connection.js +26 -13
- package/src/ws/default/default.ws.server.js +30 -12
- package/src/client/components/default/ElementsDefault.js +0 -38
- package/src/ws/core/management/core.ws.chat.js +0 -8
- package/src/ws/core/management/core.ws.mailer.js +0 -16
- package/src/ws/core/management/core.ws.stream.js +0 -8
- package/src/ws/default/management/default.ws.main.js +0 -8
|
@@ -1,35 +1,116 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Mailer WebSocket channel — manages user↔socket bidirectional mapping
|
|
3
|
+
* for targeted real-time pushes (e.g. email confirmation notifications).
|
|
4
|
+
* @module ws/core/channels/core.ws.mailer
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { IoChannel } from '../../IoInterface.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @class CoreWsMailerChannel
|
|
11
|
+
* @classdesc Manages the mailer WebSocket channel with O(1) user↔socket lookup.
|
|
12
|
+
* Handles register/unregister messages and cleanup on disconnect.
|
|
13
|
+
*/
|
|
14
|
+
class CoreWsMailerChannel {
|
|
15
|
+
/** @type {Object.<string, Object.<string, { model: { user: Object } }>>} Socket data keyed by `[wsManagementId][socketId]`. */
|
|
16
|
+
static #data = {};
|
|
17
|
+
|
|
18
|
+
/** @type {Object.<string, Object.<string, string>>} Reverse index: `[wsManagementId][userId]` → socketId. */
|
|
19
|
+
static #userIndex = {};
|
|
20
|
+
|
|
21
|
+
/** @type {IoChannel} */
|
|
22
|
+
static #io = new IoChannel({
|
|
23
|
+
channel: 'mailer',
|
|
24
|
+
controller(socket, client, payload, wsManagementId) {
|
|
25
|
+
switch (payload.status) {
|
|
26
|
+
case 'register-user':
|
|
27
|
+
CoreWsMailerChannel.setUser(wsManagementId, socket.id, payload.user);
|
|
28
|
+
break;
|
|
29
|
+
case 'unregister-user':
|
|
30
|
+
CoreWsMailerChannel.removeSocket(wsManagementId, socket.id);
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
disconnect(socket, client, reason, wsManagementId) {
|
|
37
|
+
CoreWsMailerChannel.removeSocket(wsManagementId, socket.id);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
/** @returns {Object.<string, import('socket.io').Socket>} Connected sockets map. */
|
|
42
|
+
static get client() {
|
|
43
|
+
return this.#io.client;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** @returns {string} Channel name. */
|
|
47
|
+
static get channel() {
|
|
48
|
+
return this.#io.channel;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Initializes state for a server instance.
|
|
53
|
+
* @param {string} wsManagementId - Unique server context ID (`${host}${path}`).
|
|
54
|
+
*/
|
|
55
|
+
static init(wsManagementId) {
|
|
56
|
+
this.#data[wsManagementId] = {};
|
|
57
|
+
this.#userIndex[wsManagementId] = {};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Registers a socket connection.
|
|
62
|
+
* @param {import('socket.io').Socket} socket
|
|
63
|
+
* @param {string} wsManagementId
|
|
64
|
+
*/
|
|
65
|
+
static connection(socket, wsManagementId) {
|
|
66
|
+
return this.#io.connection(socket, wsManagementId);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Handles socket disconnection.
|
|
71
|
+
* @param {import('socket.io').Socket} socket
|
|
72
|
+
* @param {string} reason
|
|
73
|
+
* @param {string} wsManagementId
|
|
74
|
+
*/
|
|
75
|
+
static disconnect(socket, reason, wsManagementId) {
|
|
76
|
+
return this.#io.disconnect(socket, reason, wsManagementId);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Registers a user↔socket mapping.
|
|
81
|
+
* @param {string} wsManagementId
|
|
82
|
+
* @param {string} socketId
|
|
83
|
+
* @param {Object} user - User data with `_id` property.
|
|
84
|
+
*/
|
|
85
|
+
static setUser(wsManagementId, socketId, user) {
|
|
86
|
+
this.#data[wsManagementId][socketId] = { model: { user } };
|
|
87
|
+
if (user?._id) {
|
|
88
|
+
this.#userIndex[wsManagementId][user._id.toString()] = socketId;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Removes a socket entry and its reverse user index.
|
|
94
|
+
* @param {string} wsManagementId
|
|
95
|
+
* @param {string} socketId
|
|
96
|
+
*/
|
|
97
|
+
static removeSocket(wsManagementId, socketId) {
|
|
98
|
+
const entry = this.#data[wsManagementId]?.[socketId];
|
|
99
|
+
if (entry?.model?.user?._id) {
|
|
100
|
+
delete this.#userIndex[wsManagementId][entry.model.user._id.toString()];
|
|
25
101
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
disconnect: function (socket, client, reason, wsManagementId) {
|
|
29
|
-
delete CoreWsMailerManagement.element[wsManagementId][socket.id];
|
|
30
|
-
},
|
|
31
|
-
};
|
|
102
|
+
delete this.#data[wsManagementId]?.[socketId];
|
|
103
|
+
}
|
|
32
104
|
|
|
33
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Finds the socket ID for a user (O(1) reverse index lookup).
|
|
107
|
+
* @param {string} wsManagementId
|
|
108
|
+
* @param {string} userId - The user `_id`.
|
|
109
|
+
* @returns {string|undefined} Socket ID, or `undefined` if not connected.
|
|
110
|
+
*/
|
|
111
|
+
static getUserWsId(wsManagementId, userId) {
|
|
112
|
+
return this.#userIndex[wsManagementId]?.[userId];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
34
115
|
|
|
35
|
-
export { CoreWsMailerChannel
|
|
116
|
+
export { CoreWsMailerChannel };
|
|
@@ -1,31 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Stream WebSocket channel — manages per-socket room membership and user tracking.
|
|
3
|
+
* @module ws/core/channels/core.ws.stream
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { IoChannel } from '../../IoInterface.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @class CoreWsStreamChannel
|
|
10
|
+
* @classdesc Manages the stream WebSocket channel. Each socket can join a room
|
|
11
|
+
* and broadcast connection/disconnection events to other room members.
|
|
12
|
+
*/
|
|
13
|
+
class CoreWsStreamChannel {
|
|
14
|
+
/** @type {Object.<string, Object.<string, Array>>} Per-socket room/user args keyed by `[wsManagementId][socketId]`. */
|
|
15
|
+
static #state = {};
|
|
16
|
+
|
|
17
|
+
/** @type {IoChannel} */
|
|
18
|
+
static #io = new IoChannel({
|
|
19
|
+
channel: 'stream',
|
|
20
|
+
stream: true,
|
|
21
|
+
controller(socket, client, payload, wsManagementId, args) {
|
|
22
|
+
const [roomId, userId] = args;
|
|
23
|
+
|
|
24
|
+
// Collect existing users in the room before registering the new one
|
|
25
|
+
const existingUsers = [];
|
|
26
|
+
for (const entry of Object.values(CoreWsStreamChannel.#state[wsManagementId])) {
|
|
27
|
+
if (entry[0] === roomId && entry[1]) existingUsers.push(entry[1]);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
CoreWsStreamChannel.#state[wsManagementId][socket.id] = args;
|
|
31
|
+
socket.join(roomId);
|
|
32
|
+
socket.to(roomId).emit('stream-user-connected', userId);
|
|
33
|
+
|
|
34
|
+
// Tell the joining user about everyone already in the room
|
|
35
|
+
if (existingUsers.length > 0) socket.emit('stream-existing-users', existingUsers);
|
|
36
|
+
},
|
|
37
|
+
connection(socket, client, wsManagementId) {
|
|
38
|
+
CoreWsStreamChannel.#state[wsManagementId][socket.id] = [];
|
|
39
|
+
},
|
|
40
|
+
disconnect(socket, client, reason, wsManagementId) {
|
|
41
|
+
const entry = CoreWsStreamChannel.#state[wsManagementId]?.[socket.id];
|
|
42
|
+
if (!entry || entry.length === 0) {
|
|
43
|
+
if (CoreWsStreamChannel.#state[wsManagementId]) delete CoreWsStreamChannel.#state[wsManagementId][socket.id];
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const [roomId, userId] = entry;
|
|
47
|
+
socket.to(roomId).emit('stream-user-disconnected', userId);
|
|
48
|
+
delete CoreWsStreamChannel.#state[wsManagementId][socket.id];
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/** @returns {Object.<string, import('socket.io').Socket>} Connected sockets map. */
|
|
53
|
+
static get client() {
|
|
54
|
+
return this.#io.client;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** @returns {string} Channel name. */
|
|
58
|
+
static get channel() {
|
|
59
|
+
return this.#io.channel;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Initializes state for a server instance.
|
|
64
|
+
* @param {string} wsManagementId - Unique server context ID (`${host}${path}`).
|
|
65
|
+
*/
|
|
66
|
+
static init(wsManagementId) {
|
|
67
|
+
this.#state[wsManagementId] = {};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Registers a socket connection.
|
|
72
|
+
* @param {import('socket.io').Socket} socket
|
|
73
|
+
* @param {string} wsManagementId
|
|
74
|
+
*/
|
|
75
|
+
static connection(socket, wsManagementId) {
|
|
76
|
+
return this.#io.connection(socket, wsManagementId);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Handles socket disconnection.
|
|
81
|
+
* @param {import('socket.io').Socket} socket
|
|
82
|
+
* @param {string} reason
|
|
83
|
+
* @param {string} wsManagementId
|
|
84
|
+
*/
|
|
85
|
+
static disconnect(socket, reason, wsManagementId) {
|
|
86
|
+
return this.#io.disconnect(socket, reason, wsManagementId);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { CoreWsStreamChannel };
|
|
@@ -1,47 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @module ws/core.ws.connection
|
|
4
|
-
* @namespace CoreWsConnection
|
|
2
|
+
* Core WebSocket connection handler — wires sockets to all channels.
|
|
3
|
+
* @module ws/core/core.ws.connection
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import { loggerFactory } from '../../server/logger.js';
|
|
8
7
|
import { CoreWsChatChannel } from './channels/core.ws.chat.js';
|
|
9
8
|
import { CoreWsMailerChannel } from './channels/core.ws.mailer.js';
|
|
10
9
|
import { CoreWsStreamChannel } from './channels/core.ws.stream.js';
|
|
11
|
-
import { Socket } from 'socket.io'; // Added for JSDoc type hinting
|
|
12
10
|
|
|
13
11
|
const logger = loggerFactory(import.meta);
|
|
14
12
|
|
|
15
13
|
/**
|
|
16
|
-
* @class
|
|
17
|
-
* @
|
|
18
|
-
*
|
|
19
|
-
* @classdesc Manages the lifecycle of a new WebSocket connection, setting up listeners for
|
|
20
|
-
* all registered channels (Chat, Mailer, Stream) and handling disconnection by delegating to channel handlers.
|
|
14
|
+
* @class CoreWsConnectionHandler
|
|
15
|
+
* @classdesc Subscribes a new socket to all core channels (chat, mailer, stream)
|
|
16
|
+
* and delegates disconnect events to each channel.
|
|
21
17
|
*/
|
|
22
|
-
class
|
|
18
|
+
class CoreWsConnectionHandler {
|
|
23
19
|
/**
|
|
24
|
-
* Handles a new WebSocket connection
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* @static
|
|
28
|
-
* @param {Socket} socket - The Socket.IO socket object representing the client connection.
|
|
29
|
-
* @param {string} wsManagementId - Unique identifier for the WebSocket management context.
|
|
30
|
-
* @returns {void}
|
|
20
|
+
* Handles a new WebSocket connection.
|
|
21
|
+
* @param {import('socket.io').Socket} socket
|
|
22
|
+
* @param {string} wsManagementId
|
|
31
23
|
*/
|
|
32
|
-
static
|
|
24
|
+
static handle(socket, wsManagementId) {
|
|
33
25
|
logger.info(`New connection established. Socket ID: ${socket.id}`);
|
|
34
26
|
|
|
35
|
-
// Subscribe socket to all channel connection handlers (assuming these channels are IoChannel instances)
|
|
36
27
|
CoreWsChatChannel.connection(socket, wsManagementId);
|
|
37
28
|
CoreWsMailerChannel.connection(socket, wsManagementId);
|
|
38
29
|
CoreWsStreamChannel.connection(socket, wsManagementId);
|
|
39
30
|
|
|
40
|
-
// Set up the disconnect listener
|
|
41
31
|
socket.on('disconnect', (reason) => {
|
|
42
|
-
logger.info(`Connection disconnected. Socket ID: ${socket.id}
|
|
32
|
+
logger.info(`Connection disconnected. Socket ID: ${socket.id}, reason: ${reason}`);
|
|
43
33
|
|
|
44
|
-
// Notify all channels of the disconnection
|
|
45
34
|
CoreWsChatChannel.disconnect(socket, reason, wsManagementId);
|
|
46
35
|
CoreWsMailerChannel.disconnect(socket, reason, wsManagementId);
|
|
47
36
|
CoreWsStreamChannel.disconnect(socket, reason, wsManagementId);
|
|
@@ -49,14 +38,4 @@ class CoreWsConnectionManager {
|
|
|
49
38
|
}
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
* Backward compatibility export for the connection handler function.
|
|
54
|
-
* @memberof CoreWsConnection
|
|
55
|
-
* @function CoreWsConnection
|
|
56
|
-
* @param {Socket} socket - The Socket.IO socket object.
|
|
57
|
-
* @param {string} wsManagementId - Unique identifier for the WebSocket management context.
|
|
58
|
-
* @returns {void}
|
|
59
|
-
*/
|
|
60
|
-
const CoreWsConnection = CoreWsConnectionManager.handleConnection;
|
|
61
|
-
|
|
62
|
-
export { CoreWsConnectionManager, CoreWsConnection };
|
|
41
|
+
export { CoreWsConnectionHandler };
|
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @module ws/core.ws.emit
|
|
4
|
-
* @namespace CoreWsEmitter
|
|
2
|
+
* Standardized WebSocket message emission.
|
|
3
|
+
* @module ws/core/core.ws.emit
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
import { loggerFactory } from '../../server/logger.js';
|
|
8
|
-
import { Socket } from 'socket.io';
|
|
9
7
|
|
|
10
8
|
const logger = loggerFactory(import.meta);
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* @class CoreWsEmitter
|
|
14
|
-
* @
|
|
15
|
-
* @memberof CoreWsEmitter
|
|
16
|
-
* @classdesc Provides a static utility method for safely emitting messages over a WebSocket connection.
|
|
12
|
+
* @classdesc Provides a static utility for safely emitting JSON-serialized messages over Socket.IO.
|
|
17
13
|
*/
|
|
18
14
|
class CoreWsEmitter {
|
|
19
15
|
/**
|
|
20
|
-
* Emits a payload to a
|
|
21
|
-
* The payload is automatically JSON stringified.
|
|
16
|
+
* Emits a JSON-stringified payload to a client on a given channel.
|
|
22
17
|
*
|
|
23
18
|
* @static
|
|
24
|
-
* @param {string}
|
|
25
|
-
* @param {Socket
|
|
26
|
-
* @param {Object}
|
|
19
|
+
* @param {string} channel - The channel/event name to emit on.
|
|
20
|
+
* @param {import('socket.io').Socket} client - The Socket.IO socket to emit to.
|
|
21
|
+
* @param {Object} payload - The data object to send.
|
|
27
22
|
* @returns {void}
|
|
28
23
|
*/
|
|
29
24
|
static emit(channel = '', client = {}, payload = {}) {
|
|
@@ -31,23 +26,12 @@ class CoreWsEmitter {
|
|
|
31
26
|
if (client && typeof client.emit === 'function') {
|
|
32
27
|
client.emit(channel, JSON.stringify(payload));
|
|
33
28
|
} else {
|
|
34
|
-
logger.error('Invalid client: Cannot emit message.', { channel,
|
|
29
|
+
logger.error('Invalid client: Cannot emit message.', { channel, payload });
|
|
35
30
|
}
|
|
36
31
|
} catch (error) {
|
|
37
|
-
logger.error(error, { channel,
|
|
32
|
+
logger.error(error, { channel, payload, stack: error.stack });
|
|
38
33
|
}
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
* Backward compatibility export for the `emit` function.
|
|
44
|
-
* @memberof CoreWsEmitter
|
|
45
|
-
* @function CoreWsEmit
|
|
46
|
-
* @param {string} [channel=''] - The name of the channel/event to emit on.
|
|
47
|
-
* @param {Socket | Object} [client={}] - The Socket.IO client/socket object.
|
|
48
|
-
* @param {Object} [payload={}] - The data object to send.
|
|
49
|
-
* @returns {void}
|
|
50
|
-
*/
|
|
51
|
-
const CoreWsEmit = CoreWsEmitter.emit;
|
|
52
|
-
|
|
53
|
-
export { CoreWsEmitter, CoreWsEmit };
|
|
37
|
+
export { CoreWsEmitter };
|
|
@@ -1,76 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* @module ws/core.ws.server
|
|
4
|
-
* @namespace CoreWsServer
|
|
2
|
+
* Core WebSocket server factory — initializes channels and creates the Socket.IO server.
|
|
3
|
+
* @module ws/core/core.ws.server
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
'use strict';
|
|
8
7
|
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import http from 'http'; // Added for JSDoc type hinting
|
|
15
|
-
|
|
16
|
-
// https://socket.io/docs/v3/
|
|
8
|
+
import { IoServer } from '../IoServer.js';
|
|
9
|
+
import { CoreWsConnectionHandler } from './core.ws.connection.js';
|
|
10
|
+
import { CoreWsChatChannel } from './channels/core.ws.chat.js';
|
|
11
|
+
import { CoreWsMailerChannel } from './channels/core.ws.mailer.js';
|
|
12
|
+
import { CoreWsStreamChannel } from './channels/core.ws.stream.js';
|
|
17
13
|
|
|
18
14
|
/**
|
|
19
|
-
* @class
|
|
20
|
-
* @
|
|
21
|
-
*
|
|
22
|
-
* @classdesc Manages the creation and initialization of the main WebSocket server,
|
|
23
|
-
* including setting up the management instances for all channels.
|
|
15
|
+
* @class CoreWsServer
|
|
16
|
+
* @classdesc Creates the core WebSocket server, initializing all channel state
|
|
17
|
+
* before attaching the connection handler.
|
|
24
18
|
*/
|
|
25
|
-
class
|
|
19
|
+
class CoreWsServer {
|
|
26
20
|
/**
|
|
27
|
-
* Initializes channel
|
|
28
|
-
*
|
|
29
|
-
* @
|
|
30
|
-
* @
|
|
31
|
-
* @param {
|
|
32
|
-
* @
|
|
33
|
-
* @param {string} options.host - The host address.
|
|
34
|
-
* @param {string} options.path - The base path for the API.
|
|
35
|
-
* @returns {Promise<Object>} The result object from IoServer creation.
|
|
21
|
+
* Initializes channel state and creates the Socket.IO server.
|
|
22
|
+
* @param {import('http').Server} httpServer
|
|
23
|
+
* @param {Object} options
|
|
24
|
+
* @param {string} options.host
|
|
25
|
+
* @param {string} options.path
|
|
26
|
+
* @returns {{ options: import('socket.io').ServerOptions, ioServer: import('socket.io').Server, meta: ImportMeta }}
|
|
36
27
|
*/
|
|
37
|
-
static
|
|
28
|
+
static create(httpServer, options) {
|
|
38
29
|
const { host, path } = options;
|
|
39
|
-
if (!host || !path) {
|
|
40
|
-
throw new Error('Host and path must be provided in server options.');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Create a unique identifier for this server instance's management context
|
|
44
30
|
const wsManagementId = `${host}${path}`;
|
|
45
31
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
CoreWsStreamManagement.instance(wsManagementId);
|
|
32
|
+
CoreWsChatChannel.init(wsManagementId);
|
|
33
|
+
CoreWsMailerChannel.init(wsManagementId);
|
|
34
|
+
CoreWsStreamChannel.init(wsManagementId);
|
|
50
35
|
|
|
51
|
-
|
|
52
|
-
return IoServerClass.create(httpServer, options, (socket) => CoreWsConnection(socket, wsManagementId));
|
|
36
|
+
return IoServer.create(httpServer, options, (socket) => CoreWsConnectionHandler.handle(socket, wsManagementId));
|
|
53
37
|
}
|
|
54
38
|
}
|
|
55
39
|
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
* @memberof CoreWsServer
|
|
59
|
-
* @function createIoServer
|
|
60
|
-
* @param {http.Server} httpServer - The HTTP server instance.
|
|
61
|
-
* @param {Object} options - Configuration options.
|
|
62
|
-
* @returns {Promise<Object>} The server creation result.
|
|
63
|
-
*/
|
|
64
|
-
const createIoServer = CoreWsServerClass.create;
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Backward compatibility alias.
|
|
68
|
-
* @memberof CoreWsServer
|
|
69
|
-
* @function CoreWsServer
|
|
70
|
-
* @param {import('http').Server} httpServer - The HTTP server instance.
|
|
71
|
-
* @param {Object} options - Configuration options.
|
|
72
|
-
* @returns {Promise<Object>} The server creation result.
|
|
73
|
-
*/
|
|
74
|
-
const CoreWsServer = createIoServer;
|
|
40
|
+
/** Required by Express.js dynamic import: `const { createIoServer } = await import(...)` */
|
|
41
|
+
const createIoServer = CoreWsServer.create.bind(CoreWsServer);
|
|
75
42
|
|
|
76
|
-
export {
|
|
43
|
+
export { CoreWsServer, createIoServer };
|
|
@@ -1,16 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Default "main" WebSocket channel — minimal no-op channel.
|
|
3
|
+
* @module ws/default/channels/default.ws.main
|
|
4
|
+
*/
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
const logger = loggerFactory(import.meta);
|
|
6
|
+
import { IoChannel } from '../../IoInterface.js';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
8
|
+
/**
|
|
9
|
+
* @class DefaultWsMainChannel
|
|
10
|
+
* @classdesc Provides a no-op main channel for the default WebSocket server.
|
|
11
|
+
*/
|
|
12
|
+
class DefaultWsMainChannel {
|
|
13
|
+
/** @type {Object.<string, Object>} Per-instance state keyed by wsManagementId. */
|
|
14
|
+
static #state = {};
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
/** @type {IoChannel} */
|
|
17
|
+
static #io = new IoChannel({ channel: 'main' });
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
/** @returns {Object.<string, import('socket.io').Socket>} Connected sockets map. */
|
|
20
|
+
static get client() {
|
|
21
|
+
return this.#io.client;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** @returns {string} Channel name. */
|
|
25
|
+
static get channel() {
|
|
26
|
+
return this.#io.channel;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Initializes state for a server instance.
|
|
31
|
+
* @param {string} wsManagementId
|
|
32
|
+
*/
|
|
33
|
+
static init(wsManagementId) {
|
|
34
|
+
this.#state[wsManagementId] = {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Registers a socket connection.
|
|
39
|
+
* @param {import('socket.io').Socket} socket
|
|
40
|
+
* @param {string} wsManagementId
|
|
41
|
+
*/
|
|
42
|
+
static connection(socket, wsManagementId) {
|
|
43
|
+
return this.#io.connection(socket, wsManagementId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Handles socket disconnection.
|
|
48
|
+
* @param {import('socket.io').Socket} socket
|
|
49
|
+
* @param {string} reason
|
|
50
|
+
* @param {string} wsManagementId
|
|
51
|
+
*/
|
|
52
|
+
static disconnect(socket, reason, wsManagementId) {
|
|
53
|
+
return this.#io.disconnect(socket, reason, wsManagementId);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { DefaultWsMainChannel };
|
|
@@ -1,22 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default WebSocket connection handler — wires sockets to the main channel.
|
|
3
|
+
* @module ws/default/default.ws.connection
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
import { loggerFactory } from '../../server/logger.js';
|
|
2
7
|
import { DefaultWsMainChannel } from './channels/default.ws.main.js';
|
|
3
8
|
|
|
4
9
|
const logger = loggerFactory(import.meta);
|
|
5
10
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* @class DefaultWsConnectionHandler
|
|
13
|
+
* @classdesc Subscribes a new socket to the default main channel
|
|
14
|
+
* and delegates disconnect events.
|
|
15
|
+
*/
|
|
16
|
+
class DefaultWsConnectionHandler {
|
|
17
|
+
/**
|
|
18
|
+
* Handles a new WebSocket connection.
|
|
19
|
+
* @param {import('socket.io').Socket} socket
|
|
20
|
+
* @param {string} wsManagementId
|
|
21
|
+
*/
|
|
22
|
+
static handle(socket, wsManagementId) {
|
|
23
|
+
logger.info(`DefaultWsConnection ${socket.id}`);
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
DefaultWsMainChannel.connection(socket, wsManagementId);
|
|
14
26
|
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
socket.on('disconnect', (reason) => {
|
|
28
|
+
logger.info(`DefaultWsConnection ${socket.id} due to reason: ${reason}`);
|
|
17
29
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
30
|
+
DefaultWsMainChannel.disconnect(socket, reason, wsManagementId);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
21
34
|
|
|
22
|
-
export {
|
|
35
|
+
export { DefaultWsConnectionHandler };
|