redweb 0.7.3 → 0.7.5
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/LICENSE +21 -21
- package/README.md +91 -252
- package/index.d.ts +165 -158
- package/index.js +19 -19
- package/package.json +27 -27
- package/src/htmx/HtmxRenderer.js +65 -65
- package/src/htmx/RedWebHtmxComponent.js +11 -11
- package/src/http/BaseHttpServer.js +102 -102
- package/src/http/HttpServer.js +14 -14
- package/src/http/HttpsServer.js +17 -17
- package/src/http/index.js +1 -1
- package/src/sslConfig.js +20 -20
- package/src/ws/BaseHandler.js +42 -24
- package/src/ws/BaseSocketServer.js +76 -76
- package/src/ws/DefaultHandler.js +13 -13
- package/src/ws/DefaultRoute.js +13 -13
- package/src/ws/SecureSocketServer.js +20 -20
- package/src/ws/SocketRegistry.js +37 -37
- package/src/ws/SocketRoute.js +142 -105
- package/src/ws/SocketServer.js +18 -18
- package/src/ws/SocketService.js +32 -32
- package/src/ws/index.js +8 -8
- package/src/ws/util.js +9 -9
package/src/ws/SocketRegistry.js
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
// handlers/SocketRegistry.js
|
|
2
|
-
const { EventEmitter } = require("events");
|
|
3
|
-
|
|
4
|
-
class SocketRegistry extends EventEmitter {
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
this.items = [];
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
add(item) {
|
|
11
|
-
this.items.push(item);
|
|
12
|
-
this.emit("added", item);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
remove(itemOrId, by = "id") {
|
|
16
|
-
const idx = typeof itemOrId === "object"
|
|
17
|
-
? this.items.findIndex(i => i === itemOrId)
|
|
18
|
-
: this.items.findIndex(i => i[by] === itemOrId);
|
|
19
|
-
|
|
20
|
-
if (idx !== -1) {
|
|
21
|
-
const [removed] = this.items.splice(idx, 1);
|
|
22
|
-
this.emit("removed", removed);
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
all() {
|
|
29
|
-
return [...this.items];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
count() {
|
|
33
|
-
return this.all().length;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = SocketRegistry;
|
|
1
|
+
// handlers/SocketRegistry.js
|
|
2
|
+
const { EventEmitter } = require("events");
|
|
3
|
+
|
|
4
|
+
class SocketRegistry extends EventEmitter {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
this.items = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
add(item) {
|
|
11
|
+
this.items.push(item);
|
|
12
|
+
this.emit("added", item);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
remove(itemOrId, by = "id") {
|
|
16
|
+
const idx = typeof itemOrId === "object"
|
|
17
|
+
? this.items.findIndex(i => i === itemOrId)
|
|
18
|
+
: this.items.findIndex(i => i[by] === itemOrId);
|
|
19
|
+
|
|
20
|
+
if (idx !== -1) {
|
|
21
|
+
const [removed] = this.items.splice(idx, 1);
|
|
22
|
+
this.emit("removed", removed);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
all() {
|
|
29
|
+
return [...this.items];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
count() {
|
|
33
|
+
return this.all().length;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = SocketRegistry;
|
package/src/ws/SocketRoute.js
CHANGED
|
@@ -1,93 +1,105 @@
|
|
|
1
|
-
const { WebSocketServer } = require("ws");
|
|
2
|
-
const { sendJson, broadcast } = require("./util");
|
|
3
|
-
const { randomUUID } = require("crypto");
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Represents a WebSocket route configuration.
|
|
7
|
-
* This class is used to define a specific WebSocket endpoint (`path`) and its associated handlers.
|
|
8
|
-
*/
|
|
9
|
-
class SocketRoute {
|
|
10
|
-
/**
|
|
11
|
-
* Creates a new instance of `SocketRoute`.
|
|
12
|
-
* @param {Object} options - Configuration options for the WebSocket route.
|
|
13
|
-
* @param {string} options.path - The path of the WebSocket route (e.g., `/chat`, `/lobby`).
|
|
1
|
+
const { WebSocketServer } = require("ws");
|
|
2
|
+
const { sendJson, broadcast } = require("./util");
|
|
3
|
+
const { randomUUID } = require("crypto");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Represents a WebSocket route configuration.
|
|
7
|
+
* This class is used to define a specific WebSocket endpoint (`path`) and its associated handlers.
|
|
8
|
+
*/
|
|
9
|
+
class SocketRoute {
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new instance of `SocketRoute`.
|
|
12
|
+
* @param {Object} options - Configuration options for the WebSocket route.
|
|
13
|
+
* @param {string} options.path - The path of the WebSocket route (e.g., `/chat`, `/lobby`).
|
|
14
14
|
* @param {boolean} options.allowDuplicateConnections - Whether to allow multiple connections from the same client IP address.
|
|
15
15
|
* @param {import('./BaseHandler').BaseHandler[]} options.handlers - An array of handler instances that manage connections and messages for this route.
|
|
16
16
|
* @param {Array<new () => SocketService>} [options.services]
|
|
17
|
+
* @param {import('ws').ServerOptions} [options.websocketOptions] - Options passed to the underlying WebSocketServer.
|
|
17
18
|
*/
|
|
18
|
-
constructor({ path, handlers, services = [], allowDuplicateConnections } = {}) {
|
|
19
|
-
if (!path) {
|
|
20
|
-
throw new Error('A `path` must be specified for the SocketRoute.');
|
|
21
|
-
}
|
|
22
|
-
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
23
|
-
throw new Error('At least one handler must be specified for the SocketRoute.');
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* The path of the WebSocket route.
|
|
27
|
-
* This determines the endpoint that clients must connect to (e.g., `ws://localhost:3000/chat`).
|
|
28
|
-
* @type {string}
|
|
29
|
-
*/
|
|
19
|
+
constructor({ path, handlers, services = [], allowDuplicateConnections, websocketOptions = {} } = {}) {
|
|
20
|
+
if (!path) {
|
|
21
|
+
throw new Error('A `path` must be specified for the SocketRoute.');
|
|
22
|
+
}
|
|
23
|
+
if (!handlers || !Array.isArray(handlers) || handlers.length === 0) {
|
|
24
|
+
throw new Error('At least one handler must be specified for the SocketRoute.');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The path of the WebSocket route.
|
|
28
|
+
* This determines the endpoint that clients must connect to (e.g., `ws://localhost:3000/chat`).
|
|
29
|
+
* @type {string}
|
|
30
|
+
*/
|
|
30
31
|
this.path = path;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
|
|
32
|
+
this.websocketOptions = websocketOptions;
|
|
33
|
+
/**
|
|
34
|
+
* The array of handler instances associated with this route.
|
|
35
|
+
* Each handler is responsible for managing WebSocket connections and message handling logic.
|
|
36
|
+
* @type {import('./BaseHandler').BaseHandler[]}
|
|
37
|
+
*/
|
|
36
38
|
this.handlers = handlers.map(HandlerClass => new HandlerClass());
|
|
37
39
|
this.clients = new Map();
|
|
38
|
-
this.server = new WebSocketServer({ noServer: true, path });
|
|
40
|
+
this.server = new WebSocketServer({ noServer: true, path, ...websocketOptions });
|
|
39
41
|
this.server.on('connection', this.handleConnection.bind(this));
|
|
40
42
|
this.allowDuplicateConnections = allowDuplicateConnections;
|
|
41
|
-
|
|
42
|
-
/* ─── ROUTE‑SCOPED SERVICES ─────────────────────────── */
|
|
43
|
-
this.services = services.map(SvcClass => {
|
|
44
|
-
const svc = new SvcClass();
|
|
45
|
-
if (typeof svc.onInit === 'function') svc.onInit(this);
|
|
46
|
-
return svc;
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Adds a new handler to the WebSocket server.
|
|
51
|
-
* @param {new () => BaseHandler} HandlerClass - The handler class to add.
|
|
52
|
-
*/
|
|
53
|
-
addHandler(HandlerClass) {
|
|
54
|
-
const newHandler = new HandlerClass();
|
|
55
|
-
if (this.handlers.find(handler => handler.name === newHandler.name)) {
|
|
56
|
-
console.warn(`Handler with name '${newHandler.name}' already exists.`);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
this.handlers.push(newHandler);
|
|
60
|
-
console.log(`Handler '${newHandler.name}' added successfully.`);
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Handles a new WebSocket connection.
|
|
64
|
-
* @param {WebSocket} socket - The WebSocket connection instance.
|
|
65
|
-
* @param {import('http').IncomingMessage} req - The HTTP request object associated with the connection.
|
|
66
|
-
*/
|
|
43
|
+
|
|
44
|
+
/* ─── ROUTE‑SCOPED SERVICES ─────────────────────────── */
|
|
45
|
+
this.services = services.map(SvcClass => {
|
|
46
|
+
const svc = new SvcClass();
|
|
47
|
+
if (typeof svc.onInit === 'function') svc.onInit(this);
|
|
48
|
+
return svc;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Adds a new handler to the WebSocket server.
|
|
53
|
+
* @param {new () => BaseHandler} HandlerClass - The handler class to add.
|
|
54
|
+
*/
|
|
55
|
+
addHandler(HandlerClass) {
|
|
56
|
+
const newHandler = new HandlerClass();
|
|
57
|
+
if (this.handlers.find(handler => handler.name === newHandler.name)) {
|
|
58
|
+
console.warn(`Handler with name '${newHandler.name}' already exists.`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
this.handlers.push(newHandler);
|
|
62
|
+
console.log(`Handler '${newHandler.name}' added successfully.`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Handles a new WebSocket connection.
|
|
66
|
+
* @param {WebSocket} socket - The WebSocket connection instance.
|
|
67
|
+
* @param {import('http').IncomingMessage} req - The HTTP request object associated with the connection.
|
|
68
|
+
*/
|
|
67
69
|
handleConnection(socket, req) {
|
|
68
|
-
const ip = req
|
|
70
|
+
const ip = req?.socket?.remoteAddress || 'unknown';
|
|
71
|
+
const clientKey = this.allowDuplicateConnections ? randomUUID() : ip;
|
|
72
|
+
|
|
69
73
|
console.log(`New client connected: ${ip}`);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
const oldClient = this.clients.get(ip);
|
|
74
|
+
|
|
75
|
+
if (!this.allowDuplicateConnections) {
|
|
76
|
+
const existing = this.clients.get(clientKey);
|
|
77
|
+
if (existing) {
|
|
75
78
|
console.warn(`Client ${ip} already connected, disconnecting existing connection.`);
|
|
76
|
-
|
|
79
|
+
existing.send(
|
|
77
80
|
JSON.stringify({ msg: 'You are being disconnected because a new client is connected with your IP address.' })
|
|
78
81
|
);
|
|
79
|
-
|
|
82
|
+
existing.close();
|
|
80
83
|
}
|
|
81
|
-
this.clients.set(ip, socket);
|
|
82
84
|
}
|
|
85
|
+
|
|
86
|
+
this.clients.set(clientKey, socket);
|
|
87
|
+
socket.clientKey = clientKey;
|
|
88
|
+
socket.__redwebClientKey = clientKey;
|
|
89
|
+
socket.remoteAddress = socket.remoteAddress || ip;
|
|
83
90
|
socket.isAssigned = false; // Tracks whether the socket has been assigned a handler.
|
|
84
91
|
socket.sendJson = (data) => sendJson(socket, data);
|
|
85
92
|
socket.broadcast = (data) => broadcast([...this.clients.values()].filter(sock => sock !== socket), data);
|
|
86
93
|
|
|
87
94
|
this.connectionOpenCallback(socket);
|
|
88
|
-
socket.on('close', this.handleClose
|
|
89
|
-
socket.on('error', this.handleError
|
|
90
|
-
socket.on('message', (message) => {
|
|
95
|
+
socket.on('close', () => this.handleClose(socket));
|
|
96
|
+
socket.on('error', (error) => this.handleError(socket, error));
|
|
97
|
+
socket.on('message', (message, isBinary) => {
|
|
98
|
+
if (isBinary) {
|
|
99
|
+
this.handleBinaryMessage(socket, message);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
try {
|
|
92
104
|
const parsed = JSON.parse(message);
|
|
93
105
|
this.handleMessage(socket, parsed);
|
|
@@ -99,52 +111,77 @@ class SocketRoute {
|
|
|
99
111
|
}
|
|
100
112
|
});
|
|
101
113
|
}
|
|
102
|
-
|
|
103
|
-
connectionOpenCallback(socket) {
|
|
104
|
-
console.log(`Opening new connection: ${socket.remoteAddress}`);
|
|
114
|
+
|
|
115
|
+
connectionOpenCallback(socket) {
|
|
116
|
+
console.log(`Opening new connection: ${socket.remoteAddress}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
handleMessage(sock, data) {
|
|
120
|
+
const handler = this.handlers.find((handler) => handler.name == data.type);
|
|
121
|
+
if (!handler) {
|
|
122
|
+
sendJson(sock, { error: `No such handler ${data.type}` });
|
|
123
|
+
sock.close();
|
|
124
|
+
} else {
|
|
125
|
+
try {
|
|
126
|
+
handler.handleMessage(sock, data);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error(`Error handling message in handler ${handler.name}:`, error);
|
|
129
|
+
sendJson(sock, { error: `${error.message}` });
|
|
130
|
+
sock.close();
|
|
131
|
+
}
|
|
132
|
+
}
|
|
105
133
|
}
|
|
106
134
|
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
135
|
+
handleBinaryMessage(socket, buffer) {
|
|
136
|
+
const hasBinaryPredicate = this.handlers.some(handler => typeof handler.acceptsBinary === 'function');
|
|
137
|
+
const handler = hasBinaryPredicate
|
|
138
|
+
? this.handlers.find(handler => handler.acceptsBinary?.(socket, buffer))
|
|
139
|
+
: this.handlers.find(handler => typeof handler.handleBinaryMessage === 'function');
|
|
140
|
+
|
|
141
|
+
if (handler) {
|
|
113
142
|
try {
|
|
114
|
-
handler.
|
|
143
|
+
handler.handleBinaryMessage(socket, buffer);
|
|
115
144
|
} catch (error) {
|
|
116
|
-
console.error(`Error handling message in handler ${handler.name}:`, error);
|
|
117
|
-
sendJson(
|
|
118
|
-
|
|
145
|
+
console.error(`Error handling binary message in handler ${handler.name}:`, error);
|
|
146
|
+
sendJson(socket, { error: `${error.message}` });
|
|
147
|
+
socket.close();
|
|
119
148
|
}
|
|
149
|
+
return;
|
|
120
150
|
}
|
|
121
|
-
}
|
|
122
151
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
152
|
+
sendJson(socket, {
|
|
153
|
+
error: 'Binary messages are not supported on this route'
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Handles socket disconnection.
|
|
159
|
+
* @param {WebSocket} socket - The WebSocket connection instance.
|
|
160
|
+
* @param {string} ip - The client's IP address.
|
|
161
|
+
*/
|
|
162
|
+
handleClose(socket) {
|
|
163
|
+
const key = socket.clientKey || socket.__redwebClientKey;
|
|
164
|
+
const ip = socket.remoteAddress || 'unknown';
|
|
129
165
|
console.log(`Client disconnected: ${ip}`);
|
|
130
|
-
this.clients.delete(
|
|
166
|
+
if (key && this.clients.get(key) === socket) this.clients.delete(key);
|
|
131
167
|
if (this.connectionCloseCallback) this.connectionCloseCallback(socket);
|
|
132
168
|
}
|
|
133
|
-
|
|
134
|
-
shutdown() {
|
|
135
|
-
this.services.forEach(svc => svc.onShutdown && svc.onShutdown());
|
|
136
|
-
this.server.close();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Handles socket errors.
|
|
141
|
-
* @param {WebSocket} socket - The WebSocket connection instance.
|
|
142
|
-
* @param {Error} error - The error object.
|
|
143
|
-
* @param {string} ip - The client's IP address.
|
|
144
|
-
*/
|
|
145
|
-
handleError(socket, error
|
|
169
|
+
|
|
170
|
+
shutdown() {
|
|
171
|
+
this.services.forEach(svc => svc.onShutdown && svc.onShutdown());
|
|
172
|
+
this.server.close();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Handles socket errors.
|
|
177
|
+
* @param {WebSocket} socket - The WebSocket connection instance.
|
|
178
|
+
* @param {Error} error - The error object.
|
|
179
|
+
* @param {string} ip - The client's IP address.
|
|
180
|
+
*/
|
|
181
|
+
handleError(socket, error) {
|
|
182
|
+
const ip = socket.remoteAddress || 'unknown';
|
|
146
183
|
console.error(`Socket error from ${ip}:`, error);
|
|
147
184
|
}
|
|
148
185
|
}
|
|
149
|
-
|
|
150
|
-
module.exports = SocketRoute;
|
|
186
|
+
|
|
187
|
+
module.exports = SocketRoute;
|
package/src/ws/SocketServer.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const { BaseSocketServer } = require('./BaseSocketServer');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* WebSocket Server
|
|
6
|
-
* @param {SocketServerOptions} options - Configuration options for SocketServer.
|
|
7
|
-
* @return {Object} WebSocket server instance.
|
|
8
|
-
*/
|
|
9
|
-
class SocketServer extends BaseSocketServer {
|
|
10
|
-
constructor(options = {}) {
|
|
11
|
-
const server = options?.server || http.createServer();
|
|
12
|
-
super(server, options);
|
|
13
|
-
server.listen(this.port, () => console.log(`RedWeb SocketServer listening on port ${this.port}`));
|
|
14
|
-
return this;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = SocketServer;
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const { BaseSocketServer } = require('./BaseSocketServer');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* WebSocket Server
|
|
6
|
+
* @param {SocketServerOptions} options - Configuration options for SocketServer.
|
|
7
|
+
* @return {Object} WebSocket server instance.
|
|
8
|
+
*/
|
|
9
|
+
class SocketServer extends BaseSocketServer {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
const server = options?.server || http.createServer();
|
|
12
|
+
super(server, options);
|
|
13
|
+
server.listen(this.port, () => console.log(`RedWeb SocketServer listening on port ${this.port}`));
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = SocketServer;
|
package/src/ws/SocketService.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
// handlers/SocketService.js
|
|
2
|
-
class SocketService {
|
|
3
|
-
/**
|
|
4
|
-
* @param {string} name – service identifier
|
|
5
|
-
* @param {?number} tickRateMs – optional tick interval (ms)
|
|
6
|
-
*/
|
|
7
|
-
constructor(name, tickRateMs = null) {
|
|
8
|
-
this.name = name;
|
|
9
|
-
this.tickRateMs = tickRateMs;
|
|
10
|
-
this._tickHandle = null;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Called once by the owning SocketRoute.
|
|
15
|
-
* @param {import('../SocketRoute')} route – the route this service belongs to
|
|
16
|
-
*/
|
|
17
|
-
onInit(route) {
|
|
18
|
-
this.route = route; // full access to route, clients, broadcast…
|
|
19
|
-
if (this.tickRateMs && this.onTick) {
|
|
20
|
-
this._tickHandle = setInterval(() => this.onTick(), this.tickRateMs);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* Optional */
|
|
25
|
-
// onTick() {}
|
|
26
|
-
|
|
27
|
-
onShutdown() {
|
|
28
|
-
if (this._tickHandle) clearInterval(this._tickHandle);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
module.exports = SocketService;
|
|
1
|
+
// handlers/SocketService.js
|
|
2
|
+
class SocketService {
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} name – service identifier
|
|
5
|
+
* @param {?number} tickRateMs – optional tick interval (ms)
|
|
6
|
+
*/
|
|
7
|
+
constructor(name, tickRateMs = null) {
|
|
8
|
+
this.name = name;
|
|
9
|
+
this.tickRateMs = tickRateMs;
|
|
10
|
+
this._tickHandle = null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Called once by the owning SocketRoute.
|
|
15
|
+
* @param {import('../SocketRoute')} route – the route this service belongs to
|
|
16
|
+
*/
|
|
17
|
+
onInit(route) {
|
|
18
|
+
this.route = route; // full access to route, clients, broadcast…
|
|
19
|
+
if (this.tickRateMs && this.onTick) {
|
|
20
|
+
this._tickHandle = setInterval(() => this.onTick(), this.tickRateMs);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Optional */
|
|
25
|
+
// onTick() {}
|
|
26
|
+
|
|
27
|
+
onShutdown() {
|
|
28
|
+
if (this._tickHandle) clearInterval(this._tickHandle);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = SocketService;
|
|
33
33
|
|
package/src/ws/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const { SOCKET_OPTIONS } = require('./BaseSocketServer');
|
|
2
|
-
module.exports = {
|
|
3
|
-
SecureSocketServer: require('./SecureSocketServer'),
|
|
4
|
-
SocketServer: require('./SocketServer'),
|
|
5
|
-
SocketRoute: require('./SocketRoute'),
|
|
6
|
-
SocketService: require('./SocketService'),
|
|
7
|
-
SocketRegistry: require('./SocketRegistry'),
|
|
8
|
-
SOCKET_OPTIONS
|
|
1
|
+
const { SOCKET_OPTIONS } = require('./BaseSocketServer');
|
|
2
|
+
module.exports = {
|
|
3
|
+
SecureSocketServer: require('./SecureSocketServer'),
|
|
4
|
+
SocketServer: require('./SocketServer'),
|
|
5
|
+
SocketRoute: require('./SocketRoute'),
|
|
6
|
+
SocketService: require('./SocketService'),
|
|
7
|
+
SocketRegistry: require('./SocketRegistry'),
|
|
8
|
+
SOCKET_OPTIONS
|
|
9
9
|
}
|
package/src/ws/util.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
function sendJson(socket, data) {
|
|
2
|
-
socket.send(JSON.stringify(data));
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
function broadcast(sockets, data) {
|
|
6
|
-
sockets.forEach(socket => sendJson(socket, data));
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
module.exports = { sendJson, broadcast }
|
|
1
|
+
function sendJson(socket, data) {
|
|
2
|
+
socket.send(JSON.stringify(data));
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function broadcast(sockets, data) {
|
|
6
|
+
sockets.forEach(socket => sendJson(socket, data));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
module.exports = { sendJson, broadcast }
|