underpost 2.8.884 → 2.8.886
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.production +3 -0
- package/.github/workflows/ghpkg.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +1 -1
- package/.github/workflows/publish.ci.yml +5 -5
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -1
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/CHANGELOG.md +145 -1
- package/Dockerfile +1 -1
- package/README.md +5 -121
- package/bin/build.js +18 -9
- package/bin/deploy.js +102 -197
- package/bin/file.js +4 -6
- package/cli.md +16 -12
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +54 -54
- package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
- package/manifests/lxd/underpost-setup.sh +5 -5
- package/package.json +3 -3
- package/scripts/ssl.sh +164 -0
- package/src/cli/baremetal.js +7 -7
- package/src/cli/cloud-init.js +1 -1
- package/src/cli/cluster.js +31 -3
- package/src/cli/cron.js +9 -1
- package/src/cli/db.js +64 -2
- package/src/cli/deploy.js +189 -4
- package/src/cli/env.js +43 -0
- package/src/cli/fs.js +96 -2
- package/src/cli/image.js +15 -0
- package/src/cli/index.js +17 -4
- package/src/cli/monitor.js +33 -2
- package/src/cli/repository.js +95 -2
- package/src/cli/run.js +315 -51
- package/src/cli/script.js +32 -0
- package/src/cli/secrets.js +34 -0
- package/src/cli/test.js +42 -1
- package/src/client/components/core/Css.js +16 -8
- package/src/client/components/core/Docs.js +5 -13
- package/src/client/components/core/Modal.js +48 -29
- package/src/client/components/core/Router.js +6 -3
- package/src/client/components/core/Worker.js +205 -118
- package/src/client/components/core/windowGetDimensions.js +229 -162
- package/src/client/components/default/MenuDefault.js +1 -0
- package/src/client.dev.js +6 -3
- package/src/db/DataBaseProvider.js +65 -12
- package/src/db/mariadb/MariaDB.js +39 -6
- package/src/db/mongo/MongooseDB.js +51 -133
- package/src/index.js +2 -2
- package/src/mailer/EmailRender.js +58 -9
- package/src/mailer/MailerProvider.js +99 -25
- package/src/runtime/express/Express.js +32 -38
- package/src/runtime/lampp/Dockerfile +1 -1
- package/src/server/auth.js +9 -28
- package/src/server/backup.js +20 -0
- package/src/server/client-build-live.js +23 -12
- package/src/server/client-build.js +136 -91
- package/src/server/client-dev-server.js +35 -8
- package/src/server/client-icons.js +19 -0
- package/src/server/conf.js +543 -80
- package/src/server/dns.js +184 -42
- package/src/server/downloader.js +65 -24
- package/src/server/object-layer.js +260 -162
- package/src/server/peer.js +3 -9
- package/src/server/proxy.js +93 -76
- package/src/server/runtime.js +15 -21
- package/src/server/ssr.js +4 -4
- package/src/server/start.js +39 -0
- package/src/server/tls.js +251 -0
- package/src/server/valkey.js +11 -10
- package/src/ws/IoInterface.js +133 -39
- package/src/ws/IoServer.js +80 -31
- package/src/ws/core/core.ws.connection.js +50 -16
- package/src/ws/core/core.ws.emit.js +47 -8
- package/src/ws/core/core.ws.server.js +62 -10
- package/manifests/maas/lxd-preseed.yaml +0 -32
- package/src/server/ssl.js +0 -108
- /package/{manifests/maas → scripts}/device-scan.sh +0 -0
- /package/{manifests/maas → scripts}/gpu-diag.sh +0 -0
- /package/{manifests/maas → scripts}/maas-setup.sh +0 -0
- /package/{manifests/maas → scripts}/nat-iptables.sh +0 -0
- /package/{manifests/maas → scripts}/nvim.sh +0 -0
- /package/{manifests/maas → scripts}/snap-clean.sh +0 -0
- /package/{manifests/maas → scripts}/ssh-cluster-info.sh +0 -0
package/src/server/valkey.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Module for managing Valkey
|
|
3
3
|
* @module src/server/valkey.js
|
|
4
|
-
* @namespace
|
|
4
|
+
* @namespace ValkeyService
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import Valkey from 'iovalkey';
|
|
@@ -20,7 +20,7 @@ const ValkeyStatus = {}; // 'connected' | 'dummy' | 'error' | undefined
|
|
|
20
20
|
* Checks if any Valkey instance is connected.
|
|
21
21
|
* This is a backward-compatible overall flag.
|
|
22
22
|
* @returns {boolean} True if any instance has a 'connected' status.
|
|
23
|
-
* @memberof
|
|
23
|
+
* @memberof ValkeyService
|
|
24
24
|
*/
|
|
25
25
|
const isValkeyEnable = () => Object.values(ValkeyStatus).some((s) => s === 'connected');
|
|
26
26
|
|
|
@@ -31,7 +31,7 @@ const isValkeyEnable = () => Object.values(ValkeyStatus).some((s) => s === 'conn
|
|
|
31
31
|
* @param {string} [opts.path=''] - The path of the instance.
|
|
32
32
|
* @returns {string} The instance key.
|
|
33
33
|
* @private
|
|
34
|
-
* @memberof
|
|
34
|
+
* @memberof ValkeyService
|
|
35
35
|
*/
|
|
36
36
|
const _instanceKey = (opts = { host: '', path: '' }) => `${opts.host || ''}${opts.path || ''}`;
|
|
37
37
|
|
|
@@ -43,7 +43,7 @@ const _instanceKey = (opts = { host: '', path: '' }) => `${opts.host || ''}${opt
|
|
|
43
43
|
* @param {string} [instance.path=''] - The path of the instance.
|
|
44
44
|
* @param {object} [valkeyServerConnectionOptions={ host: '', path: '' }] - Connection options for the iovalkey client.
|
|
45
45
|
* @returns {Promise<Valkey|undefined>} A promise that resolves to the Valkey client instance, or undefined if creation fails.
|
|
46
|
-
* @memberof
|
|
46
|
+
* @memberof ValkeyService
|
|
47
47
|
*/
|
|
48
48
|
const createValkeyConnection = async (
|
|
49
49
|
instance = { host: '', path: '' },
|
|
@@ -108,7 +108,7 @@ const createValkeyConnection = async (
|
|
|
108
108
|
* @param {object} payload - The source object.
|
|
109
109
|
* @param {object} select - An object where keys are field names and values are 1 to include them.
|
|
110
110
|
* @returns {object} A new object containing only the selected fields from the payload.
|
|
111
|
-
* @memberof
|
|
111
|
+
* @memberof ValkeyService
|
|
112
112
|
*/
|
|
113
113
|
const selectDtoFactory = (payload, select) => {
|
|
114
114
|
const result = {};
|
|
@@ -122,7 +122,7 @@ const selectDtoFactory = (payload, select) => {
|
|
|
122
122
|
* Factory function to create a new Valkey client instance.
|
|
123
123
|
* @param {object} options - Connection options for the iovalkey client.
|
|
124
124
|
* @returns {Promise<Valkey>} A promise that resolves to a new Valkey client.
|
|
125
|
-
* @memberof
|
|
125
|
+
* @memberof ValkeyService
|
|
126
126
|
*/
|
|
127
127
|
const valkeyClientFactory = async (options) => {
|
|
128
128
|
const valkey = new Valkey({
|
|
@@ -154,7 +154,7 @@ const valkeyClientFactory = async (options) => {
|
|
|
154
154
|
* @param {object} [options={ host: '', path: '' }] - The instance identifier.
|
|
155
155
|
* @param {string} [key=''] - The key of the object to retrieve.
|
|
156
156
|
* @returns {Promise<object|string|null>} A promise that resolves to the retrieved object, string, or null if not found.
|
|
157
|
-
* @memberof
|
|
157
|
+
* @memberof ValkeyService
|
|
158
158
|
*/
|
|
159
159
|
const getValkeyObject = async (options = { host: '', path: '' }, key = '') => {
|
|
160
160
|
const k = _instanceKey(options);
|
|
@@ -185,7 +185,7 @@ const getValkeyObject = async (options = { host: '', path: '' }, key = '') => {
|
|
|
185
185
|
* @param {string} [key=''] - The key under which to store the payload.
|
|
186
186
|
* @param {object|string} [payload={}] - The data to store.
|
|
187
187
|
* @returns {Promise<string>} A promise that resolves to 'OK' on success.
|
|
188
|
-
* @memberof
|
|
188
|
+
* @memberof ValkeyService
|
|
189
189
|
*/
|
|
190
190
|
const setValkeyObject = async (options = { host: '', path: '' }, key = '', payload = {}) => {
|
|
191
191
|
const k = _instanceKey(options);
|
|
@@ -212,7 +212,7 @@ const setValkeyObject = async (options = { host: '', path: '' }, key = '', paylo
|
|
|
212
212
|
* @param {string} [key=''] - The key of the object to update.
|
|
213
213
|
* @param {object} [payload={}] - The new data to merge into the object.
|
|
214
214
|
* @returns {Promise<string>} A promise that resolves to the result of the set operation.
|
|
215
|
-
* @memberof
|
|
215
|
+
* @memberof ValkeyService
|
|
216
216
|
*/
|
|
217
217
|
const updateValkeyObject = async (options = { host: '', path: '' }, key = '', payload = {}) => {
|
|
218
218
|
let base = await getValkeyObject(options, key);
|
|
@@ -230,7 +230,7 @@ const updateValkeyObject = async (options = { host: '', path: '' }, key = '', pa
|
|
|
230
230
|
* @param {object} [options.object={}] - An initial object to extend.
|
|
231
231
|
* @param {string} [model=''] - The name of the model schema to use (e.g., 'user').
|
|
232
232
|
* @returns {Promise<object>} A promise that resolves to the newly created object.
|
|
233
|
-
* @memberof
|
|
233
|
+
* @memberof ValkeyService
|
|
234
234
|
*/
|
|
235
235
|
const valkeyObjectFactory = async (options = { host: 'localhost', path: '', object: {} }, model = '') => {
|
|
236
236
|
const idoDate = new Date().toISOString();
|
|
@@ -268,6 +268,7 @@ const valkeyObjectFactory = async (options = { host: 'localhost', path: '', obje
|
|
|
268
268
|
/**
|
|
269
269
|
* A collection of Valkey-related API functions.
|
|
270
270
|
* @type {object}
|
|
271
|
+
* @memberof ValkeyServiceService
|
|
271
272
|
*/
|
|
272
273
|
const ValkeyAPI = {
|
|
273
274
|
valkeyClientFactory,
|
package/src/ws/IoInterface.js
CHANGED
|
@@ -1,45 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for creating and managing WebSocket channels.
|
|
3
|
+
* @module src/ws/IoInterface.js
|
|
4
|
+
* @namespace SocketIoInterface
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { loggerFactory } from '../server/logger.js';
|
|
8
|
+
import { Socket } from 'socket.io';
|
|
2
9
|
|
|
3
10
|
const logger = loggerFactory(import.meta);
|
|
4
11
|
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Defines the structure for a WebSocket channel's behavior functions.
|
|
14
|
+
* @typedef {Object} ChannelInterface
|
|
15
|
+
* @property {string} channel - The name of the channel.
|
|
16
|
+
* @property {function(Socket, Object.<string, Socket>, string): Promise<void>} [connection] - Handler on client connection.
|
|
17
|
+
* @property {function(Socket, Object.<string, Socket>, any, string, any[]): Promise<void>} [controller] - Handler for incoming channel messages.
|
|
18
|
+
* @property {function(Socket, Object.<string, Socket>, string, string): Promise<void>} [disconnect] - Handler on client disconnection.
|
|
19
|
+
* @property {boolean} [stream=false] - Whether the channel should treat the message as a raw stream (no JSON parsing).
|
|
20
|
+
* @memberof SocketIoInterface
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @class IoChannel
|
|
25
|
+
* @alias IoChannel
|
|
26
|
+
* @memberof SocketIoInterface
|
|
27
|
+
* @classdesc Manages the logic, client map, and event listeners for a specific WebSocket channel,
|
|
28
|
+
* ensuring robust message handling and lifecycle management.
|
|
29
|
+
*/
|
|
30
|
+
class IoChannel {
|
|
31
|
+
/**
|
|
32
|
+
* @private
|
|
33
|
+
* @type {ChannelInterface}
|
|
34
|
+
*/
|
|
35
|
+
#IoInterface;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Map of connected sockets for this channel, keyed by socket ID.
|
|
39
|
+
* @type {Object.<string, Socket>}
|
|
40
|
+
*/
|
|
41
|
+
client = {};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Creates an instance of IoChannel.
|
|
45
|
+
* @param {ChannelInterface} IoInterface - The interface object defining the channel's behavior.
|
|
46
|
+
*/
|
|
47
|
+
constructor(IoInterface) {
|
|
48
|
+
this.#IoInterface = {
|
|
49
|
+
channel: '',
|
|
50
|
+
connection: async (socket = {}, client = {}, wsManagementId = '') => {},
|
|
51
|
+
controller: async (socket = {}, client = {}, payload = {}, wsManagementId = '', args = []) => {},
|
|
52
|
+
disconnect: async (socket = {}, client = {}, reason = '', wsManagementId = '') => {},
|
|
53
|
+
stream: false,
|
|
54
|
+
...IoInterface,
|
|
55
|
+
};
|
|
56
|
+
logger.debug(`Channel instance created for: ${this.channel}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gets the name of the channel.
|
|
61
|
+
* @returns {string} The channel name.
|
|
62
|
+
*/
|
|
63
|
+
get channel() {
|
|
64
|
+
return this.#IoInterface.channel;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Handles a new socket connection for this channel.
|
|
69
|
+
* Sets up the listener for the channel message.
|
|
70
|
+
*
|
|
71
|
+
* @param {Socket} socket - The Socket.IO socket object.
|
|
72
|
+
* @param {string} wsManagementId - Unique identifier for the WebSocket management context.
|
|
73
|
+
* @returns {Promise<void>}
|
|
74
|
+
*/
|
|
75
|
+
async connection(socket, wsManagementId) {
|
|
76
|
+
try {
|
|
77
|
+
this.client[socket.id] = socket;
|
|
78
|
+
// Use bind/arrow function to maintain 'this' context for the controller
|
|
79
|
+
socket.on(this.channel, (...args) => this.controller(socket, args, wsManagementId));
|
|
80
|
+
await this.#IoInterface.connection(socket, this.client, wsManagementId);
|
|
81
|
+
logger.debug(`Socket ${socket.id} connected to channel ${this.channel}`);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
logger.error(error, { channel: this.channel, wsManagementId, stack: error.stack });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Handles incoming messages on the channel.
|
|
89
|
+
*
|
|
90
|
+
* @private
|
|
91
|
+
* @param {Socket} socket - The Socket.IO socket object.
|
|
92
|
+
* @param {any[]} args - The raw arguments received from the socket event.
|
|
93
|
+
* @param {string} wsManagementId - Unique identifier for the WebSocket management context.
|
|
94
|
+
* @returns {Promise<void>}
|
|
95
|
+
*/
|
|
96
|
+
async controller(socket, args, wsManagementId) {
|
|
97
|
+
try {
|
|
98
|
+
if (!args || args.length === 0) {
|
|
99
|
+
logger.warn(`No arguments received for channel: ${this.channel}`, { socketId: socket.id });
|
|
100
|
+
return;
|
|
40
101
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
102
|
+
// Determine if JSON parsing is needed based on the stream flag
|
|
103
|
+
const payload = this.#IoInterface.stream ? args[0] : JSON.parse(args[0]);
|
|
104
|
+
|
|
105
|
+
await this.#IoInterface.controller(socket, this.client, payload, wsManagementId, args);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
logger.error(error, { channel: this.channel, wsManagementId, socketId: socket.id, args, stack: error.stack });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Handles a socket disconnection for this channel.
|
|
113
|
+
*
|
|
114
|
+
* @param {Socket} socket - The Socket.IO socket object.
|
|
115
|
+
* @param {string} reason - The reason for disconnection (e.g., 'client namespace disconnect').
|
|
116
|
+
* @param {string} wsManagementId - Unique identifier for the WebSocket management context.
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
async disconnect(socket, reason, wsManagementId) {
|
|
120
|
+
try {
|
|
121
|
+
await this.#IoInterface.disconnect(socket, this.client, reason, wsManagementId);
|
|
122
|
+
delete this.client[socket.id];
|
|
123
|
+
logger.debug(`Socket ${socket.id} disconnected from channel ${this.channel}. Reason: ${reason}`);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
logger.error(error, { channel: this.channel, wsManagementId, reason, socketId: socket.id, stack: error.stack });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Backward compatibility function to create a new channel instance.
|
|
132
|
+
* @memberof SocketIoInterface
|
|
133
|
+
* @function IoCreateChannel
|
|
134
|
+
* @param {ChannelInterface} IoInterface - The interface object defining the channel's behavior.
|
|
135
|
+
* @returns {IoChannel} An instance of the IoChannel class.
|
|
136
|
+
*/
|
|
137
|
+
const IoCreateChannel = (IoInterface) => new IoChannel(IoInterface);
|
|
44
138
|
|
|
45
|
-
export { IoCreateChannel };
|
|
139
|
+
export { IoChannel, IoCreateChannel };
|
package/src/ws/IoServer.js
CHANGED
|
@@ -1,39 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for creating and managing WebSocket servers.
|
|
3
|
+
* @module src/ws/IoServer
|
|
4
|
+
* @namespace SocketIoServer
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
'use strict';
|
|
2
8
|
|
|
3
9
|
import { Server } from 'socket.io';
|
|
4
10
|
import { loggerFactory } from '../server/logger.js';
|
|
11
|
+
import UnderpostStartUp from '../server/start.js';
|
|
5
12
|
|
|
6
|
-
|
|
13
|
+
import http from 'http';
|
|
7
14
|
|
|
8
15
|
const logger = loggerFactory(import.meta);
|
|
9
16
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
options
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
17
|
+
/**
|
|
18
|
+
* @class IoServerClass
|
|
19
|
+
* @alias IoServerClass
|
|
20
|
+
* @memberof SocketIoServer
|
|
21
|
+
* @classdesc Provides a static factory method to create and configure a Socket.IO server,
|
|
22
|
+
* encapsulating WebSocket server initialization logic and CORS configuration.
|
|
23
|
+
*/
|
|
24
|
+
class IoServerClass {
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new WebSocket server instance attached to an HTTP server.
|
|
27
|
+
*
|
|
28
|
+
* @static
|
|
29
|
+
* @param {http.Server} httpServer - The HTTP server instance to attach the WebSocket server to.
|
|
30
|
+
* @param {Object} options - Configuration options for the WebSocket server.
|
|
31
|
+
* @param {string[]} options.origins - List of allowed origins for Cross-Origin Resource Sharing (CORS).
|
|
32
|
+
* @param {string} options.path - The base path for the API. The WebSocket path ('/socket.io') will be appended to this.
|
|
33
|
+
* @param {function(import('socket.io').Socket): void} ConnectionHandler - The connection handler function to be executed on a new connection.
|
|
34
|
+
* @returns {Object} An object containing the final options and the server instance.
|
|
35
|
+
* @returns {import('socket.io').ServerOptions} return.options - The final options object used to create the WebSocket server.
|
|
36
|
+
* @returns {import('socket.io').Server} return.ioServer - The created and listening WebSocket server instance.
|
|
37
|
+
* @returns {object} return.meta - The module's import meta object (`import.meta`).
|
|
38
|
+
*/
|
|
39
|
+
static create(httpServer, options = {}, ConnectionHandler = () => {}) {
|
|
40
|
+
logger.info('origins', options.origins);
|
|
41
|
+
const wsOptions = {
|
|
42
|
+
cors: {
|
|
43
|
+
origins: options.origins,
|
|
44
|
+
methods: ['GET', 'POST', 'DELETE', 'PUT'],
|
|
45
|
+
allowedHeaders: [
|
|
46
|
+
'Access-Control-Allow-Headers',
|
|
47
|
+
'Access-Control-Allow-Origin',
|
|
48
|
+
'X-Requested-With',
|
|
49
|
+
'X-Access-Token',
|
|
50
|
+
'Content-Type',
|
|
51
|
+
'Host',
|
|
52
|
+
'Accept',
|
|
53
|
+
'Connection',
|
|
54
|
+
'Cache-Control',
|
|
55
|
+
'Authorization',
|
|
56
|
+
],
|
|
57
|
+
credentials: true,
|
|
58
|
+
},
|
|
59
|
+
// Ensure the path ends correctly, appending '/socket.io/'
|
|
60
|
+
path: options.path !== '/' ? `${options.path}/socket.io/` : '/socket.io/',
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const ioServerInstance = UnderpostStartUp.API.listenServerFactory(() =>
|
|
64
|
+
new Server(httpServer, wsOptions).on('connection', ConnectionHandler),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
logger.info('Socket.IO Server created and listening', { path: wsOptions.path });
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
options: wsOptions,
|
|
71
|
+
meta: import.meta,
|
|
72
|
+
ioServer: ioServerInstance,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Backward compatibility export for the server creation function.
|
|
79
|
+
* @memberof SocketIoServer
|
|
80
|
+
* @function IoServer
|
|
81
|
+
* @param {http.Server} httpServer - The HTTP server instance.
|
|
82
|
+
* @param {Object} options - Configuration options.
|
|
83
|
+
* @param {function(import('socket.io').Socket): void} ConnectionHandler - The connection handler function.
|
|
84
|
+
* @returns {Object} The server configuration object.
|
|
85
|
+
*/
|
|
86
|
+
const IoServer = IoServerClass.create;
|
|
87
|
+
|
|
88
|
+
export { IoServerClass, IoServer };
|
|
@@ -1,28 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for handling new WebSocket connections and setting up channel listeners.
|
|
3
|
+
* @module ws/core.ws.connection
|
|
4
|
+
* @namespace CoreWsConnection
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { loggerFactory } from '../../server/logger.js';
|
|
2
8
|
import { CoreWsChatChannel } from './channels/core.ws.chat.js';
|
|
3
9
|
import { CoreWsMailerChannel } from './channels/core.ws.mailer.js';
|
|
4
10
|
import { CoreWsStreamChannel } from './channels/core.ws.stream.js';
|
|
11
|
+
import { Socket } from 'socket.io'; // Added for JSDoc type hinting
|
|
5
12
|
|
|
6
13
|
const logger = loggerFactory(import.meta);
|
|
7
14
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
/**
|
|
16
|
+
* @class CoreWsConnectionManager
|
|
17
|
+
* @alias CoreWsConnectionManager
|
|
18
|
+
* @memberof CoreWsConnection
|
|
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.
|
|
21
|
+
*/
|
|
22
|
+
class CoreWsConnectionManager {
|
|
23
|
+
/**
|
|
24
|
+
* Handles a new WebSocket connection by subscribing it to all active channels
|
|
25
|
+
* and setting up the disconnect listener.
|
|
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}
|
|
31
|
+
*/
|
|
32
|
+
static handleConnection(socket, wsManagementId) {
|
|
33
|
+
logger.info(`New connection established. Socket ID: ${socket.id}`);
|
|
12
34
|
|
|
13
|
-
|
|
35
|
+
// Subscribe socket to all channel connection handlers (assuming these channels are IoChannel instances)
|
|
36
|
+
CoreWsChatChannel.connection(socket, wsManagementId);
|
|
37
|
+
CoreWsMailerChannel.connection(socket, wsManagementId);
|
|
38
|
+
CoreWsStreamChannel.connection(socket, wsManagementId);
|
|
14
39
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
40
|
+
// Set up the disconnect listener
|
|
41
|
+
socket.on('disconnect', (reason) => {
|
|
42
|
+
logger.info(`Connection disconnected. Socket ID: ${socket.id} due to reason: ${reason}`);
|
|
18
43
|
|
|
19
|
-
|
|
20
|
-
|
|
44
|
+
// Notify all channels of the disconnection
|
|
45
|
+
CoreWsChatChannel.disconnect(socket, reason, wsManagementId);
|
|
46
|
+
CoreWsMailerChannel.disconnect(socket, reason, wsManagementId);
|
|
47
|
+
CoreWsStreamChannel.disconnect(socket, reason, wsManagementId);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
21
51
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
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;
|
|
27
61
|
|
|
28
|
-
export { CoreWsConnection };
|
|
62
|
+
export { CoreWsConnectionManager, CoreWsConnection };
|
|
@@ -1,14 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for standardized WebSocket message emission (sending).
|
|
3
|
+
* @module ws/core.ws.emit
|
|
4
|
+
* @namespace CoreWsEmitter
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { loggerFactory } from '../../server/logger.js';
|
|
8
|
+
import { Socket } from 'socket.io';
|
|
2
9
|
|
|
3
10
|
const logger = loggerFactory(import.meta);
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
/**
|
|
13
|
+
* @class CoreWsEmitter
|
|
14
|
+
* @alias CoreWsEmitter
|
|
15
|
+
* @memberof CoreWsEmitter
|
|
16
|
+
* @classdesc Provides a static utility method for safely emitting messages over a WebSocket connection.
|
|
17
|
+
*/
|
|
18
|
+
class CoreWsEmitter {
|
|
19
|
+
/**
|
|
20
|
+
* Emits a payload to a specific client over a given channel.
|
|
21
|
+
* The payload is automatically JSON stringified.
|
|
22
|
+
*
|
|
23
|
+
* @static
|
|
24
|
+
* @param {string} [channel=''] - The name of the channel/event to emit on.
|
|
25
|
+
* @param {Socket | Object} [client={}] - The Socket.IO client/socket object. Must have an `emit` method.
|
|
26
|
+
* @param {Object} [payload={}] - The data object to send.
|
|
27
|
+
* @returns {void}
|
|
28
|
+
*/
|
|
29
|
+
static emit(channel = '', client = {}, payload = {}) {
|
|
30
|
+
try {
|
|
31
|
+
if (client && typeof client.emit === 'function') {
|
|
32
|
+
client.emit(channel, JSON.stringify(payload));
|
|
33
|
+
} else {
|
|
34
|
+
logger.error('Invalid client: Cannot emit message.', { channel, client, payload });
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error(error, { channel, client, payload, stack: error.stack });
|
|
38
|
+
}
|
|
11
39
|
}
|
|
12
|
-
}
|
|
40
|
+
}
|
|
41
|
+
|
|
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;
|
|
13
52
|
|
|
14
|
-
export { CoreWsEmit };
|
|
53
|
+
export { CoreWsEmitter, CoreWsEmit };
|
|
@@ -1,24 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module for creating and initializing the main WebSocket server instance.
|
|
3
|
+
* @module ws/core.ws.server
|
|
4
|
+
* @namespace CoreWsServer
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
'use strict';
|
|
2
8
|
|
|
3
|
-
import {
|
|
9
|
+
import { IoServerClass } from '../IoServer.js';
|
|
4
10
|
import { CoreWsConnection } from './core.ws.connection.js';
|
|
5
11
|
import { CoreWsChatManagement } from './management/core.ws.chat.js';
|
|
6
12
|
import { CoreWsMailerManagement } from './management/core.ws.mailer.js';
|
|
7
13
|
import { CoreWsStreamManagement } from './management/core.ws.stream.js';
|
|
14
|
+
import http from 'http'; // Added for JSDoc type hinting
|
|
8
15
|
|
|
9
16
|
// https://socket.io/docs/v3/
|
|
10
17
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
18
|
+
/**
|
|
19
|
+
* @class CoreWsServerClass
|
|
20
|
+
* @alias CoreWsServerClass
|
|
21
|
+
* @memberof CoreWsServer
|
|
22
|
+
* @classdesc Manages the creation and initialization of the main WebSocket server,
|
|
23
|
+
* including setting up the management instances for all channels.
|
|
24
|
+
*/
|
|
25
|
+
class CoreWsServerClass {
|
|
26
|
+
/**
|
|
27
|
+
* Initializes channel management instances and creates the Socket.IO server.
|
|
28
|
+
*
|
|
29
|
+
* @static
|
|
30
|
+
* @async
|
|
31
|
+
* @param {http.Server} httpServer - The HTTP server instance to attach the WebSocket server to.
|
|
32
|
+
* @param {Object} options - Configuration options for the WebSocket server.
|
|
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.
|
|
36
|
+
*/
|
|
37
|
+
static async create(httpServer, options) {
|
|
38
|
+
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
|
+
const wsManagementId = `${host}${path}`;
|
|
45
|
+
|
|
46
|
+
// Initialize/Retrieve singleton management instances for all channels
|
|
47
|
+
CoreWsChatManagement.instance(wsManagementId);
|
|
48
|
+
CoreWsMailerManagement.instance(wsManagementId);
|
|
49
|
+
CoreWsStreamManagement.instance(wsManagementId);
|
|
14
50
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
51
|
+
// Use the IoServerClass factory to create the server, passing the connection handler
|
|
52
|
+
return IoServerClass.create(httpServer, options, (socket) => CoreWsConnection(socket, wsManagementId));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
18
55
|
|
|
19
|
-
|
|
20
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Backward compatibility export for the server creation function.
|
|
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;
|
|
21
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
|
+
*/
|
|
22
74
|
const CoreWsServer = createIoServer;
|
|
23
75
|
|
|
24
|
-
export { createIoServer, CoreWsServer };
|
|
76
|
+
export { CoreWsServerClass, createIoServer, CoreWsServer };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
config:
|
|
2
|
-
core.https_address: "[::]:8443"
|
|
3
|
-
# core.trust_password: password
|
|
4
|
-
networks:
|
|
5
|
-
- config:
|
|
6
|
-
ipv4.address: 10.10.10.1/24
|
|
7
|
-
ipv6.address: none
|
|
8
|
-
description: ""
|
|
9
|
-
name: lxdbr0
|
|
10
|
-
type: ""
|
|
11
|
-
project: default
|
|
12
|
-
storage_pools:
|
|
13
|
-
- config:
|
|
14
|
-
size: 500GB
|
|
15
|
-
description: ""
|
|
16
|
-
name: default
|
|
17
|
-
driver: zfs
|
|
18
|
-
profiles:
|
|
19
|
-
- config: {}
|
|
20
|
-
description: ""
|
|
21
|
-
devices:
|
|
22
|
-
eth0:
|
|
23
|
-
name: eth0
|
|
24
|
-
network: lxdbr0
|
|
25
|
-
type: nic
|
|
26
|
-
root:
|
|
27
|
-
path: /
|
|
28
|
-
pool: default
|
|
29
|
-
type: disk
|
|
30
|
-
name: default
|
|
31
|
-
projects: []
|
|
32
|
-
cluster: null
|