topsyde-utils 1.3.2 → 2.0.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.
Files changed (94) hide show
  1. package/dist/index.d.ts +2 -31
  2. package/dist/index.js +1 -27
  3. package/dist/index.js.map +1 -1
  4. package/dist/utils/Lib.d.ts +0 -12
  5. package/dist/utils/Lib.js +0 -65
  6. package/dist/utils/Lib.js.map +1 -1
  7. package/dist/websocket.shared.types.d.ts +25 -0
  8. package/dist/websocket.shared.types.js +4 -0
  9. package/dist/websocket.shared.types.js.map +1 -0
  10. package/package.json +1 -22
  11. package/src/index.ts +2 -51
  12. package/src/utils/Lib.ts +0 -77
  13. package/src/websocket.shared.types.ts +27 -0
  14. package/dist/application.d.ts +0 -18
  15. package/dist/application.js +0 -60
  16. package/dist/application.js.map +0 -1
  17. package/dist/server/base/base.database.d.ts +0 -10
  18. package/dist/server/base/base.database.js +0 -23
  19. package/dist/server/base/base.database.js.map +0 -1
  20. package/dist/server/base/index.d.ts +0 -2
  21. package/dist/server/base/index.js +0 -5
  22. package/dist/server/base/index.js.map +0 -1
  23. package/dist/server/bun/index.d.ts +0 -3
  24. package/dist/server/bun/index.js +0 -6
  25. package/dist/server/bun/index.js.map +0 -1
  26. package/dist/server/bun/router/controller-discovery.d.ts +0 -13
  27. package/dist/server/bun/router/controller-discovery.js +0 -83
  28. package/dist/server/bun/router/controller-discovery.js.map +0 -1
  29. package/dist/server/bun/router/index.d.ts +0 -6
  30. package/dist/server/bun/router/index.js +0 -9
  31. package/dist/server/bun/router/index.js.map +0 -1
  32. package/dist/server/bun/router/router.d.ts +0 -12
  33. package/dist/server/bun/router/router.internal.d.ts +0 -15
  34. package/dist/server/bun/router/router.internal.js +0 -51
  35. package/dist/server/bun/router/router.internal.js.map +0 -1
  36. package/dist/server/bun/router/router.js +0 -38
  37. package/dist/server/bun/router/router.js.map +0 -1
  38. package/dist/server/bun/router/routes.d.ts +0 -5
  39. package/dist/server/bun/router/routes.js +0 -2
  40. package/dist/server/bun/router/routes.js.map +0 -1
  41. package/dist/server/bun/websocket/Channel.d.ts +0 -68
  42. package/dist/server/bun/websocket/Channel.js +0 -263
  43. package/dist/server/bun/websocket/Channel.js.map +0 -1
  44. package/dist/server/bun/websocket/Client.d.ts +0 -87
  45. package/dist/server/bun/websocket/Client.js +0 -193
  46. package/dist/server/bun/websocket/Client.js.map +0 -1
  47. package/dist/server/bun/websocket/Message.d.ts +0 -10
  48. package/dist/server/bun/websocket/Message.js +0 -103
  49. package/dist/server/bun/websocket/Message.js.map +0 -1
  50. package/dist/server/bun/websocket/Websocket.d.ts +0 -171
  51. package/dist/server/bun/websocket/Websocket.js +0 -336
  52. package/dist/server/bun/websocket/Websocket.js.map +0 -1
  53. package/dist/server/bun/websocket/index.d.ts +0 -11
  54. package/dist/server/bun/websocket/index.js +0 -14
  55. package/dist/server/bun/websocket/index.js.map +0 -1
  56. package/dist/server/bun/websocket/websocket.enums.d.ts +0 -27
  57. package/dist/server/bun/websocket/websocket.enums.js +0 -31
  58. package/dist/server/bun/websocket/websocket.enums.js.map +0 -1
  59. package/dist/server/bun/websocket/websocket.guards.d.ts +0 -3
  60. package/dist/server/bun/websocket/websocket.guards.js +0 -17
  61. package/dist/server/bun/websocket/websocket.guards.js.map +0 -1
  62. package/dist/server/bun/websocket/websocket.types.d.ts +0 -235
  63. package/dist/server/bun/websocket/websocket.types.js +0 -2
  64. package/dist/server/bun/websocket/websocket.types.js.map +0 -1
  65. package/dist/server/controller.d.ts +0 -62
  66. package/dist/server/controller.js +0 -55
  67. package/dist/server/controller.js.map +0 -1
  68. package/dist/server/index.d.ts +0 -4
  69. package/dist/server/index.js +0 -7
  70. package/dist/server/index.js.map +0 -1
  71. package/dist/server/service.d.ts +0 -5
  72. package/dist/server/service.js +0 -38
  73. package/dist/server/service.js.map +0 -1
  74. package/src/application.ts +0 -73
  75. package/src/server/base/base.database.ts +0 -31
  76. package/src/server/base/index.ts +0 -5
  77. package/src/server/bun/index.ts +0 -6
  78. package/src/server/bun/router/controller-discovery.ts +0 -94
  79. package/src/server/bun/router/index.ts +0 -9
  80. package/src/server/bun/router/router.internal.ts +0 -64
  81. package/src/server/bun/router/router.ts +0 -51
  82. package/src/server/bun/router/routes.ts +0 -7
  83. package/src/server/bun/websocket/Channel.ts +0 -310
  84. package/src/server/bun/websocket/Client.ts +0 -243
  85. package/src/server/bun/websocket/ISSUES.md +0 -1175
  86. package/src/server/bun/websocket/Message.ts +0 -120
  87. package/src/server/bun/websocket/Websocket.ts +0 -402
  88. package/src/server/bun/websocket/index.ts +0 -14
  89. package/src/server/bun/websocket/websocket.enums.ts +0 -29
  90. package/src/server/bun/websocket/websocket.guards.ts +0 -22
  91. package/src/server/bun/websocket/websocket.types.ts +0 -252
  92. package/src/server/controller.ts +0 -121
  93. package/src/server/index.ts +0 -7
  94. package/src/server/service.ts +0 -36
@@ -1,336 +0,0 @@
1
- import Singleton from "../../../singleton.js";
2
- import { Lib } from "../../../utils/index.js";
3
- import { Console } from "../../../utils/Console.js";
4
- import Channel from "./Channel.js";
5
- import Client from "./Client.js";
6
- import { E_WebsocketMessageType } from "./websocket.enums.js";
7
- /**
8
- * Websocket - Singleton managing clients, channels, and message routing
9
- *
10
- * ## API Design: Static vs Instance
11
- * - **Static methods**: Use in application code (e.g., `Websocket.Broadcast()`, `Websocket.GetClient()`)
12
- * - **Instance methods**: Use when extending the class (e.g., `protected createClient()`)
13
- *
14
- * Static methods are facades that call the singleton instance internally.
15
- *
16
- * @example
17
- * // Application code - use static methods
18
- * Websocket.Broadcast("lobby", { type: "chat", content: { message: "Hi!" } });
19
- *
20
- * // Extension - override instance methods
21
- * MyWebsocket extends Websocket:
22
- * protected createClient(entity) {
23
- * return new MyCustomClient(entity);
24
- * }
25
- */
26
- export default class Websocket extends Singleton {
27
- constructor(options) {
28
- super();
29
- this._clients = new Map();
30
- this._lastId = 1;
31
- this.clientMessageReceived = (ws, message) => {
32
- try {
33
- if (Websocket.Heartbeat(ws, message))
34
- return;
35
- if (this._ws_interface_handlers.message)
36
- return this._ws_interface_handlers.message(ws, message);
37
- ws.send("This is the message from the server: " + message);
38
- Websocket.BroadCastAll({ type: "client.message.received", content: { message } });
39
- }
40
- catch (error) {
41
- console.error(error instanceof Error ? error.message : error);
42
- ws.close(1011, "Internal server error during message handling: " + (error instanceof Error ? error.message : error));
43
- }
44
- };
45
- this.clientConnected = (ws) => {
46
- try {
47
- if (this._options.debug)
48
- Lib.Log("[debug] Client connected", ws.data);
49
- const global = this._channels.get("global");
50
- if (!global)
51
- throw new Error("Global channel not found");
52
- const client = Websocket.CreateClient({ id: ws.data.id, ws: ws, name: ws.data.name });
53
- this._clients.set(client.id, client);
54
- this._lastId++;
55
- if ((Number(client.id) || 0) >= this._lastId)
56
- this._lastId = Number(client.id) + 1;
57
- // Mark as fully connected
58
- client.markConnected();
59
- client.send({ type: E_WebsocketMessageType.CLIENT_CONNECTED, content: { message: "Welcome to the server", client: client.whoami() } });
60
- // Client handles its own joining logic with rollback support
61
- const joinResult = client.joinChannel(global);
62
- if (!joinResult.success) {
63
- throw new Error("Failed to join global channel: " + joinResult.reason);
64
- }
65
- if (this._ws_interface_handlers.open)
66
- this._ws_interface_handlers.open(ws);
67
- }
68
- catch (error) {
69
- console.error(error instanceof Error ? error.message : error);
70
- ws.close(1011, "Internal server error during connection setup: " + (error instanceof Error ? error.message : error));
71
- }
72
- };
73
- this.clientDisconnected = (ws, code, reason) => {
74
- try {
75
- if (this._options.debug)
76
- Lib.Log("Client disconnected", ws.data);
77
- const client = this._clients.get(ws.data.id);
78
- if (!client)
79
- return;
80
- // Mark as disconnecting
81
- client.markDisconnecting();
82
- if (this._ws_interface_handlers.close)
83
- this._ws_interface_handlers.close(ws, code, reason);
84
- // Remove from all channels
85
- this._channels.forEach((channel) => {
86
- channel.removeMember(client);
87
- });
88
- // Remove from registry
89
- this._clients.delete(ws.data.id);
90
- // Mark as disconnected
91
- client.markDisconnected();
92
- }
93
- catch (error) {
94
- console.error(error instanceof Error ? error.message : error);
95
- ws.close(1011, "Internal server error during disconnection: " + (error instanceof Error ? error.message : error));
96
- }
97
- };
98
- this.handleHeartbeat = (ws, message) => {
99
- if (message === "ping") {
100
- const pong = { type: "pong", content: { message: "pong" } };
101
- ws.send(JSON.stringify(pong));
102
- return true;
103
- }
104
- return false;
105
- };
106
- this._ws_interface = options?.ws_interface;
107
- this._channels = options?.channels ?? new Map();
108
- this._clientClass = options?.clientClass ?? Client;
109
- this._channelClass = options?.channelClass ?? Channel.GetChannelType(options?.channels);
110
- this._options = options?.options ?? { debug: false };
111
- this.createChannel("global", "Global", this._options.global_channel_limit ?? 1000);
112
- this._ws_interface_handlers = this._ws_interface?.handlers(this._channels, this._clients) ?? {};
113
- }
114
- set server(value) {
115
- this._server = value;
116
- }
117
- get server() {
118
- return this._server;
119
- }
120
- set(server) {
121
- this.server = server;
122
- Console.blank();
123
- Console.success("Websocket server set");
124
- }
125
- /**
126
- * Create a new channel
127
- * @param id - The id of the channel
128
- * @param name - The name of the channel
129
- * @param limit - The limit of the channel
130
- * @returns The created channel
131
- */
132
- createChannel(id, name, limit) {
133
- if (this._channels.has(id))
134
- return this._channels.get(id);
135
- const channel = new this._channelClass(id, name, this, limit);
136
- this._channels.set(id, channel);
137
- return channel;
138
- }
139
- /**
140
- * Remove a channel
141
- * @param id - The id of the channel
142
- */
143
- removeChannel(id) {
144
- const channel = this._channels.get(id);
145
- if (!channel)
146
- return;
147
- channel.delete();
148
- this._channels.delete(id);
149
- }
150
- /**
151
- * Create a new channel
152
- * @param id - The id of the channel
153
- * @param name - The name of the channel
154
- * @param limit - The limit of the channel
155
- * @returns The created channel
156
- */
157
- static CreateChannel(id, name, limit) {
158
- const ws = this.GetInstance();
159
- return ws.createChannel(id, name, limit);
160
- }
161
- handlers() {
162
- return {
163
- open: this.clientConnected,
164
- message: this.clientMessageReceived,
165
- close: this.clientDisconnected,
166
- };
167
- }
168
- createClient(entity) {
169
- return new this._clientClass(entity);
170
- }
171
- /**
172
- * Handle the heartbeat
173
- * @param ws - The websocket
174
- * @param message - The message
175
- * @returns True if the heartbeat was handled, false otherwise
176
- */
177
- static Heartbeat(ws, message) {
178
- const self = this.GetInstance();
179
- return self.handleHeartbeat(ws, message);
180
- }
181
- /**
182
- * Get the server
183
- * @returns The server
184
- */
185
- static Server() {
186
- return this.GetInstance().server;
187
- }
188
- /**
189
- * Broadcast a message to a channel
190
- * @param channel - The channel
191
- * @param message - The message
192
- * @param args - The arguments
193
- */
194
- static Broadcast(channel, message, ...args) {
195
- // Get the server from the singleton instance
196
- const ws = this.GetInstance();
197
- if (!ws.server) {
198
- throw new Error("Websocket server not set");
199
- }
200
- ws.server.publish(channel, JSON.stringify({ message, args }));
201
- }
202
- /**
203
- * Broadcast a message to all channels
204
- * @param message - The message
205
- * @param args - The arguments
206
- */
207
- static BroadCastAll(message, ...args) {
208
- const ws = this.GetInstance();
209
- ws._channels.forEach((channel) => channel.broadcast(message, ...args));
210
- }
211
- /**
212
- * Join a channel
213
- * @param channel - The channel
214
- * @param entity - The entity
215
- */
216
- static Join(channel, entity) {
217
- const ws = this.GetInstance();
218
- const client = ws._clients.get(entity.id);
219
- if (!client)
220
- return;
221
- ws._channels.get(channel)?.addMember(client);
222
- }
223
- /**
224
- * Leave a channel
225
- * @param channel - The channel
226
- * @param entity - The entity
227
- */
228
- static Leave(channel, entity) {
229
- const ws = this.GetInstance();
230
- const client = ws._clients.get(entity.id);
231
- if (!client)
232
- return;
233
- ws._channels.get(channel)?.removeMember(client);
234
- }
235
- static GetClient(id, throw_if_nil = true) {
236
- const ws = this.GetInstance();
237
- const client = ws._clients.get(id);
238
- if (!client && throw_if_nil)
239
- throw new Error(`Client with id ${id} not found`);
240
- return client;
241
- }
242
- /**
243
- * Get a channel
244
- * @param id - The id of the channel
245
- * @returns The channel
246
- */
247
- static GetChannel(id) {
248
- const ws = this.GetInstance();
249
- return ws._channels.get(id);
250
- }
251
- /**
252
- * Get all channels
253
- * @returns The channels
254
- */
255
- static GetChannels() {
256
- const ws = this.GetInstance();
257
- return Array.from(ws._channels.values());
258
- }
259
- /**
260
- * Get all clients
261
- * @returns The clients
262
- */
263
- static GetClients() {
264
- const ws = this.GetInstance();
265
- return Array.from(ws._clients.values());
266
- }
267
- static GetLastId() {
268
- const ws = this.GetInstance();
269
- return ws._lastId;
270
- }
271
- /**
272
- * Get the number of clients
273
- * @returns The number of clients
274
- */
275
- static GetClientCount() {
276
- const ws = this.GetInstance();
277
- return ws._clients.size;
278
- }
279
- /**
280
- * Get the number of channels
281
- * @returns The number of channels
282
- */
283
- static GetChannelCount() {
284
- const ws = this.GetInstance();
285
- return ws._channels.size;
286
- }
287
- /**
288
- * Create a client
289
- * @param entity - The entity
290
- * @returns The created client
291
- */
292
- static CreateClient(entity) {
293
- const ws = this.GetInstance();
294
- return ws.createClient(entity);
295
- }
296
- /**
297
- * Get all connected clients (excluding connecting/disconnecting)
298
- * @returns Array of connected clients
299
- */
300
- static GetConnectedClients() {
301
- const ws = this.GetInstance();
302
- return Array.from(ws._clients.values()).filter((client) => client.state === "connected");
303
- }
304
- /**
305
- * Get client statistics by state
306
- * @returns Object with counts by state
307
- */
308
- static GetClientStats() {
309
- const ws = this.GetInstance();
310
- const stats = {
311
- total: ws._clients.size,
312
- connecting: 0,
313
- connected: 0,
314
- disconnecting: 0,
315
- disconnected: 0,
316
- };
317
- for (const client of ws._clients.values()) {
318
- switch (client.state) {
319
- case "connecting":
320
- stats.connecting++;
321
- break;
322
- case "connected":
323
- stats.connected++;
324
- break;
325
- case "disconnecting":
326
- stats.disconnecting++;
327
- break;
328
- case "disconnected":
329
- stats.disconnected++;
330
- break;
331
- }
332
- }
333
- return stats;
334
- }
335
- }
336
- //# sourceMappingURL=Websocket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Websocket.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/Websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { Server, ServerWebSocket, WebSocketHandler } from \"bun\";\nimport Singleton from \"../../../singleton\";\nimport { Lib } from \"../../../utils\";\nimport { Console } from \"../../../utils/Console\";\nimport Channel from \"./Channel\";\nimport Client from \"./Client\";\nimport type {\n\tI_WebsocketChannel,\n\tI_WebsocketClient,\n\tI_WebsocketEntity,\n\tI_WebsocketInterface,\n\tWebsocketChannel,\n\tWebsocketEntityData,\n\tBunWebsocketMessage,\n\tWebsocketStructuredMessage,\n} from \"./websocket.types\";\nimport { E_WebsocketMessageType } from \"./websocket.enums\";\n\nexport type WebsocketConstructorOptions = {\n\tdebug?: boolean;\n\tglobal_channel_limit?: number;\n};\n\nexport interface I_WebsocketConstructor {\n\tws_interface?: I_WebsocketInterface;\n\tchannels?: WebsocketChannel;\n\tclientClass?: typeof Client;\n\tchannelClass?: typeof Channel;\n\toptions?: WebsocketConstructorOptions;\n}\n\n/**\n * Websocket - Singleton managing clients, channels, and message routing\n *\n * ## API Design: Static vs Instance\n * - **Static methods**: Use in application code (e.g., `Websocket.Broadcast()`, `Websocket.GetClient()`)\n * - **Instance methods**: Use when extending the class (e.g., `protected createClient()`)\n *\n * Static methods are facades that call the singleton instance internally.\n *\n * @example\n * // Application code - use static methods\n * Websocket.Broadcast(\"lobby\", { type: \"chat\", content: { message: \"Hi!\" } });\n *\n * // Extension - override instance methods\n * MyWebsocket extends Websocket:\n * protected createClient(entity) {\n * return new MyCustomClient(entity);\n * }\n */\nexport default class Websocket extends Singleton {\n\tprotected _channels: WebsocketChannel;\n\tprotected _clients: Map<string, I_WebsocketClient> = new Map();\n\tprotected _server!: Server;\n\tprotected _channelClass: typeof Channel;\n\tprotected _clientClass: typeof Client;\n\tprotected _ws_interface?: I_WebsocketInterface;\n\tprotected _options: WebsocketConstructorOptions;\n\tprotected _ws_interface_handlers: Partial<WebSocketHandler<WebsocketEntityData>>;\n\tprotected _lastId = 1;\n\n\tprotected constructor(options?: I_WebsocketConstructor) {\n\t\tsuper();\n\t\tthis._ws_interface = options?.ws_interface;\n\t\tthis._channels = options?.channels ?? new Map<string, Channel>();\n\t\tthis._clientClass = options?.clientClass ?? Client;\n\t\tthis._channelClass = options?.channelClass ?? Channel.GetChannelType(options?.channels);\n\t\tthis._options = options?.options ?? { debug: false };\n\t\tthis.createChannel(\"global\", \"Global\", this._options.global_channel_limit ?? 1000);\n\t\tthis._ws_interface_handlers = this._ws_interface?.handlers(this._channels, this._clients) ?? {};\n\t}\n\n\tprotected set server(value: Server) {\n\t\tthis._server = value;\n\t}\n\n\tpublic get server(): Server {\n\t\treturn this._server;\n\t}\n\n\tpublic set(server: Server) {\n\t\tthis.server = server;\n\t\tConsole.blank();\n\t\tConsole.success(\"Websocket server set\");\n\t}\n\n\t/**\n\t * Create a new channel\n\t * @param id - The id of the channel\n\t * @param name - The name of the channel\n\t * @param limit - The limit of the channel\n\t * @returns The created channel\n\t */\n\tpublic createChannel(id: string, name: string, limit?: number): Channel {\n\t\tif (this._channels.has(id)) return this._channels.get(id) as Channel;\n\t\tconst channel = new this._channelClass(id, name, this, limit);\n\t\tthis._channels.set(id, channel);\n\t\treturn channel;\n\t}\n\n\t/**\n\t * Remove a channel\n\t * @param id - The id of the channel\n\t */\n\tpublic removeChannel(id: string) {\n\t\tconst channel = this._channels.get(id);\n\t\tif (!channel) return;\n\t\tchannel.delete();\n\t\tthis._channels.delete(id);\n\t}\n\n\t/**\n\t * Create a new channel\n\t * @param id - The id of the channel\n\t * @param name - The name of the channel\n\t * @param limit - The limit of the channel\n\t * @returns The created channel\n\t */\n\tpublic static CreateChannel(id: string, name: string, limit?: number) {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws.createChannel(id, name, limit);\n\t}\n\n\tpublic handlers(): WebSocketHandler<WebsocketEntityData> {\n\t\treturn {\n\t\t\topen: this.clientConnected,\n\t\t\tmessage: this.clientMessageReceived,\n\t\t\tclose: this.clientDisconnected,\n\t\t};\n\t}\n\n\tprivate clientMessageReceived = (ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) => {\n\t\ttry {\n\t\t\tif (Websocket.Heartbeat(ws, message)) return;\n\n\t\t\tif (this._ws_interface_handlers.message) return this._ws_interface_handlers.message(ws, message);\n\n\t\t\tws.send(\"This is the message from the server: \" + message);\n\t\t\tWebsocket.BroadCastAll({ type: \"client.message.received\", content: { message } });\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\t\tws.close(1011, \"Internal server error during message handling: \" + (error instanceof Error ? error.message : error));\n\t\t}\n\t};\n\n\tprivate clientConnected = (ws: ServerWebSocket<WebsocketEntityData>) => {\n\t\ttry {\n\t\t\tif (this._options.debug) Lib.Log(\"[debug] Client connected\", ws.data);\n\n\t\t\tconst global = this._channels.get(\"global\");\n\t\t\tif (!global) throw new Error(\"Global channel not found\");\n\n\t\t\tconst client = Websocket.CreateClient({ id: ws.data.id, ws: ws, name: ws.data.name });\n\t\t\tthis._clients.set(client.id, client);\n\t\t\tthis._lastId++;\n\t\t\tif ((Number(client.id) || 0) >= this._lastId) this._lastId = Number(client.id) + 1;\n\n\t\t\t// Mark as fully connected\n\t\t\tclient.markConnected();\n\n\t\t\tclient.send({ type: E_WebsocketMessageType.CLIENT_CONNECTED, content: { message: \"Welcome to the server\", client: client.whoami() } });\n\n\t\t\t// Client handles its own joining logic with rollback support\n\t\t\tconst joinResult = client.joinChannel(global);\n\t\t\tif (!joinResult.success) {\n\t\t\t\tthrow new Error(\"Failed to join global channel: \" + joinResult.reason);\n\t\t\t}\n\n\t\t\tif (this._ws_interface_handlers.open) this._ws_interface_handlers.open(ws);\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\t\tws.close(1011, \"Internal server error during connection setup: \" + (error instanceof Error ? error.message : error));\n\t\t}\n\t};\n\n\tprivate clientDisconnected = (ws: ServerWebSocket<WebsocketEntityData>, code: number, reason: string) => {\n\t\ttry {\n\t\t\tif (this._options.debug) Lib.Log(\"Client disconnected\", ws.data);\n\n\t\t\tconst client = this._clients.get(ws.data.id);\n\t\t\tif (!client) return;\n\n\t\t\t// Mark as disconnecting\n\t\t\tclient.markDisconnecting();\n\n\t\t\tif (this._ws_interface_handlers.close) this._ws_interface_handlers.close(ws, code, reason);\n\n\t\t\t// Remove from all channels\n\t\t\tthis._channels.forEach((channel) => {\n\t\t\t\tchannel.removeMember(client);\n\t\t\t});\n\n\t\t\t// Remove from registry\n\t\t\tthis._clients.delete(ws.data.id);\n\t\t\t// Mark as disconnected\n\t\t\tclient.markDisconnected();\n\t\t} catch (error) {\n\t\t\tconsole.error(error instanceof Error ? error.message : error);\n\t\t\tws.close(1011, \"Internal server error during disconnection: \" + (error instanceof Error ? error.message : error));\n\t\t}\n\t};\n\n\tprivate handleHeartbeat = (ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) => {\n\t\tif (message === \"ping\") {\n\t\t\tconst pong: WebsocketStructuredMessage = { type: \"pong\", content: { message: \"pong\" } };\n\t\t\tws.send(JSON.stringify(pong));\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t};\n\n\tprotected createClient(entity: I_WebsocketEntity): I_WebsocketClient {\n\t\treturn new this._clientClass(entity);\n\t}\n\n\t/**\n\t * Handle the heartbeat\n\t * @param ws - The websocket\n\t * @param message - The message\n\t * @returns True if the heartbeat was handled, false otherwise\n\t */\n\tpublic static Heartbeat(ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) {\n\t\tconst self = this.GetInstance<Websocket>();\n\t\treturn self.handleHeartbeat(ws, message);\n\t}\n\n\t/**\n\t * Get the server\n\t * @returns The server\n\t */\n\tpublic static Server() {\n\t\treturn this.GetInstance<Websocket>().server;\n\t}\n\n\t/**\n\t * Broadcast a message to a channel\n\t * @param channel - The channel\n\t * @param message - The message\n\t * @param args - The arguments\n\t */\n\tpublic static Broadcast(channel: string, message: WebsocketStructuredMessage, ...args: any[]) {\n\t\t// Get the server from the singleton instance\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tif (!ws.server) {\n\t\t\tthrow new Error(\"Websocket server not set\");\n\t\t}\n\t\tws.server.publish(channel, JSON.stringify({ message, args }));\n\t}\n\n\t/**\n\t * Broadcast a message to all channels\n\t * @param message - The message\n\t * @param args - The arguments\n\t */\n\tpublic static BroadCastAll(message: WebsocketStructuredMessage, ...args: any[]) {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tws._channels.forEach((channel) => channel.broadcast(message, ...args));\n\t}\n\n\t/**\n\t * Join a channel\n\t * @param channel - The channel\n\t * @param entity - The entity\n\t */\n\tpublic static Join(channel: string, entity: I_WebsocketEntity) {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tconst client = ws._clients.get(entity.id);\n\t\tif (!client) return;\n\t\tws._channels.get(channel)?.addMember(client);\n\t}\n\n\t/**\n\t * Leave a channel\n\t * @param channel - The channel\n\t * @param entity - The entity\n\t */\n\tpublic static Leave(channel: string, entity: I_WebsocketEntity) {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tconst client = ws._clients.get(entity.id);\n\t\tif (!client) return;\n\t\tws._channels.get(channel)?.removeMember(client);\n\t}\n\n\t/**\n\t * Get a client\n\t * @param id - The id of the client\n\t * @param throw_if_nil - Whether to throw an error if the client is not found\n\t * @returns The client\n\t */\n\tpublic static GetClient(id: string, throw_if_nil?: true): I_WebsocketClient;\n\tpublic static GetClient(id: string, throw_if_nil?: false): I_WebsocketClient | undefined;\n\tpublic static GetClient(id: string, throw_if_nil: boolean = true): I_WebsocketClient | undefined {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tconst client = ws._clients.get(id);\n\t\tif (!client && throw_if_nil) throw new Error(`Client with id ${id} not found`);\n\t\treturn client;\n\t}\n\n\t/**\n\t * Get a channel\n\t * @param id - The id of the channel\n\t * @returns The channel\n\t */\n\tpublic static GetChannel(id: string) {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws._channels.get(id);\n\t}\n\n\t/**\n\t * Get all channels\n\t * @returns The channels\n\t */\n\tpublic static GetChannels() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn Array.from(ws._channels.values());\n\t}\n\n\t/**\n\t * Get all clients\n\t * @returns The clients\n\t */\n\tpublic static GetClients() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn Array.from(ws._clients.values());\n\t}\n\n\tpublic static GetLastId() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws._lastId;\n\t}\n\n\t/**\n\t * Get the number of clients\n\t * @returns The number of clients\n\t */\n\tpublic static GetClientCount() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws._clients.size;\n\t}\n\n\t/**\n\t * Get the number of channels\n\t * @returns The number of channels\n\t */\n\tpublic static GetChannelCount() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws._channels.size;\n\t}\n\n\t/**\n\t * Create a client\n\t * @param entity - The entity\n\t * @returns The created client\n\t */\n\tpublic static CreateClient(entity: I_WebsocketEntity): I_WebsocketClient {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn ws.createClient(entity);\n\t}\n\n\t/**\n\t * Get all connected clients (excluding connecting/disconnecting)\n\t * @returns Array of connected clients\n\t */\n\tpublic static GetConnectedClients(): I_WebsocketClient[] {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\treturn Array.from(ws._clients.values()).filter((client) => client.state === \"connected\");\n\t}\n\n\t/**\n\t * Get client statistics by state\n\t * @returns Object with counts by state\n\t */\n\tpublic static GetClientStats() {\n\t\tconst ws = this.GetInstance<Websocket>();\n\t\tconst stats = {\n\t\t\ttotal: ws._clients.size,\n\t\t\tconnecting: 0,\n\t\t\tconnected: 0,\n\t\t\tdisconnecting: 0,\n\t\t\tdisconnected: 0,\n\t\t};\n\n\t\tfor (const client of ws._clients.values()) {\n\t\t\tswitch (client.state) {\n\t\t\t\tcase \"connecting\":\n\t\t\t\t\tstats.connecting++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"connected\":\n\t\t\t\t\tstats.connected++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"disconnecting\":\n\t\t\t\t\tstats.disconnecting++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"disconnected\":\n\t\t\t\t\tstats.disconnected++;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn stats;\n\t}\n}\n"]}
@@ -1,11 +0,0 @@
1
- export * from './Websocket';
2
- export * from './websocket.guards';
3
- export * from './Message';
4
- export * from './Channel';
5
- export * from './Client';
6
- export * from './websocket.enums';
7
- export * from './websocket.types';
8
- export { default as Websocket } from './Websocket';
9
- export { default as Message } from './Message';
10
- export { default as Channel } from './Channel';
11
- export { default as Client } from './Client';
@@ -1,14 +0,0 @@
1
- // This file is auto-generated by scripts/generate-indexes.ts
2
- // Do not edit this file directly
3
- export * from './Websocket.js';
4
- export * from './websocket.guards.js';
5
- export * from './Message.js';
6
- export * from './Channel.js';
7
- export * from './Client.js';
8
- export * from './websocket.enums.js';
9
- export * from './websocket.types.js';
10
- export { default as Websocket } from './Websocket.js';
11
- export { default as Message } from './Message.js';
12
- export { default as Channel } from './Channel.js';
13
- export { default as Client } from './Client.js';
14
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,iCAAiC;AAEjC,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC","sourcesContent":["// This file is auto-generated by scripts/generate-indexes.ts\n// Do not edit this file directly\n\nexport * from './Websocket';\nexport * from './websocket.guards';\nexport * from './Message';\nexport * from './Channel';\nexport * from './Client';\nexport * from './websocket.enums';\nexport * from './websocket.types';\nexport { default as Websocket } from './Websocket';\nexport { default as Message } from './Message';\nexport { default as Channel } from './Channel';\nexport { default as Client } from './Client';\n"]}
@@ -1,27 +0,0 @@
1
- export declare enum E_WebsocketMessageType {
2
- CLIENT_CONNECTED = "client.connected",
3
- CLIENT_DISCONNECTED = "client.disconnected",
4
- CLIENT_JOIN_CHANNEL = "client.join.channel",
5
- CLIENT_LEAVE_CHANNEL = "client.leave.channel",
6
- CLIENT_JOIN_CHANNELS = "client.join.channels",
7
- CLIENT_LEAVE_CHANNELS = "client.leave.channels",
8
- PING = "ping",
9
- PONG = "pong",
10
- MESSAGE = "message",
11
- WHISPER = "whisper",
12
- BROADCAST = "broadcast",
13
- PROMPT = "prompt",
14
- ERROR = "error",
15
- SYSTEM = "system"
16
- }
17
- export declare enum E_WebsocketMessagePriority {
18
- LOW = 0,
19
- MEDIUM = 1,
20
- HIGH = 2
21
- }
22
- export declare enum E_ClientState {
23
- CONNECTING = "connecting",
24
- CONNECTED = "connected",
25
- DISCONNECTING = "disconnecting",
26
- DISCONNECTED = "disconnected"
27
- }
@@ -1,31 +0,0 @@
1
- export var E_WebsocketMessageType;
2
- (function (E_WebsocketMessageType) {
3
- E_WebsocketMessageType["CLIENT_CONNECTED"] = "client.connected";
4
- E_WebsocketMessageType["CLIENT_DISCONNECTED"] = "client.disconnected";
5
- E_WebsocketMessageType["CLIENT_JOIN_CHANNEL"] = "client.join.channel";
6
- E_WebsocketMessageType["CLIENT_LEAVE_CHANNEL"] = "client.leave.channel";
7
- E_WebsocketMessageType["CLIENT_JOIN_CHANNELS"] = "client.join.channels";
8
- E_WebsocketMessageType["CLIENT_LEAVE_CHANNELS"] = "client.leave.channels";
9
- E_WebsocketMessageType["PING"] = "ping";
10
- E_WebsocketMessageType["PONG"] = "pong";
11
- E_WebsocketMessageType["MESSAGE"] = "message";
12
- E_WebsocketMessageType["WHISPER"] = "whisper";
13
- E_WebsocketMessageType["BROADCAST"] = "broadcast";
14
- E_WebsocketMessageType["PROMPT"] = "prompt";
15
- E_WebsocketMessageType["ERROR"] = "error";
16
- E_WebsocketMessageType["SYSTEM"] = "system";
17
- })(E_WebsocketMessageType || (E_WebsocketMessageType = {}));
18
- export var E_WebsocketMessagePriority;
19
- (function (E_WebsocketMessagePriority) {
20
- E_WebsocketMessagePriority[E_WebsocketMessagePriority["LOW"] = 0] = "LOW";
21
- E_WebsocketMessagePriority[E_WebsocketMessagePriority["MEDIUM"] = 1] = "MEDIUM";
22
- E_WebsocketMessagePriority[E_WebsocketMessagePriority["HIGH"] = 2] = "HIGH";
23
- })(E_WebsocketMessagePriority || (E_WebsocketMessagePriority = {}));
24
- export var E_ClientState;
25
- (function (E_ClientState) {
26
- E_ClientState["CONNECTING"] = "connecting";
27
- E_ClientState["CONNECTED"] = "connected";
28
- E_ClientState["DISCONNECTING"] = "disconnecting";
29
- E_ClientState["DISCONNECTED"] = "disconnected";
30
- })(E_ClientState || (E_ClientState = {}));
31
- //# sourceMappingURL=websocket.enums.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket.enums.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/websocket.enums.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,sBAeX;AAfD,WAAY,sBAAsB;IACjC,+DAAqC,CAAA;IACrC,qEAA2C,CAAA;IAC3C,qEAA2C,CAAA;IAC3C,uEAA6C,CAAA;IAC7C,uEAA6C,CAAA;IAC7C,yEAA+C,CAAA;IAC/C,uCAAa,CAAA;IACb,uCAAa,CAAA;IACb,6CAAmB,CAAA;IACnB,6CAAmB,CAAA;IACnB,iDAAuB,CAAA;IACvB,2CAAiB,CAAA;IACjB,yCAAe,CAAA;IACf,2CAAiB,CAAA;AAClB,CAAC,EAfW,sBAAsB,KAAtB,sBAAsB,QAejC;AAED,MAAM,CAAN,IAAY,0BAIX;AAJD,WAAY,0BAA0B;IACrC,yEAAO,CAAA;IACP,+EAAU,CAAA;IACV,2EAAQ,CAAA;AACT,CAAC,EAJW,0BAA0B,KAA1B,0BAA0B,QAIrC;AAED,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACxB,0CAAyB,CAAA;IACzB,wCAAuB,CAAA;IACvB,gDAA+B,CAAA;IAC/B,8CAA6B,CAAA;AAC9B,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB","sourcesContent":["export enum E_WebsocketMessageType {\n\tCLIENT_CONNECTED = \"client.connected\",\n\tCLIENT_DISCONNECTED = \"client.disconnected\",\n\tCLIENT_JOIN_CHANNEL = \"client.join.channel\",\n\tCLIENT_LEAVE_CHANNEL = \"client.leave.channel\",\n\tCLIENT_JOIN_CHANNELS = \"client.join.channels\",\n\tCLIENT_LEAVE_CHANNELS = \"client.leave.channels\",\n\tPING = \"ping\",\n\tPONG = \"pong\",\n\tMESSAGE = \"message\",\n\tWHISPER = \"whisper\",\n\tBROADCAST = \"broadcast\",\n\tPROMPT = \"prompt\",\n\tERROR = \"error\",\n\tSYSTEM = \"system\",\n}\n\nexport enum E_WebsocketMessagePriority {\n\tLOW = 0,\n\tMEDIUM = 1,\n\tHIGH = 2,\n}\n\nexport enum E_ClientState {\n\tCONNECTING = \"connecting\",\n\tCONNECTED = \"connected\",\n\tDISCONNECTING = \"disconnecting\",\n\tDISCONNECTED = \"disconnected\",\n}\n"]}
@@ -1,3 +0,0 @@
1
- import { I_WebsocketEntity, WebsocketStructuredMessage } from "./websocket.types";
2
- export declare function IsWebsocketStructuredMessage(message: any): message is WebsocketStructuredMessage;
3
- export declare function IsWebsocketEntity(entity: any): entity is I_WebsocketEntity;
@@ -1,17 +0,0 @@
1
- export function IsWebsocketStructuredMessage(message) {
2
- return typeof message === "object" && message !== null && "type" in message && "content" in message;
3
- }
4
- export function IsWebsocketEntity(entity) {
5
- return (typeof entity === "object" &&
6
- entity !== null &&
7
- "id" in entity &&
8
- "name" in entity &&
9
- "ws" in entity &&
10
- typeof entity.ws === "object" &&
11
- entity.ws !== null &&
12
- "send" in entity.ws &&
13
- typeof entity.ws.send === "function" &&
14
- "close" in entity.ws &&
15
- typeof entity.ws.close === "function");
16
- }
17
- //# sourceMappingURL=websocket.guards.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket.guards.js","sourceRoot":"","sources":["../../../../src/server/bun/websocket/websocket.guards.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,4BAA4B,CAAC,OAAY;IACxD,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,MAAM,IAAI,OAAO,IAAI,SAAS,IAAI,OAAO,CAAC;AACrG,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAW;IAC5C,OAAO,CACN,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,IAAI,IAAI,MAAM;QACd,MAAM,IAAI,MAAM;QAChB,IAAI,IAAI,MAAM;QACd,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ;QAC7B,MAAM,CAAC,EAAE,KAAK,IAAI;QAClB,MAAM,IAAI,MAAM,CAAC,EAAE;QACnB,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,UAAU;QACpC,OAAO,IAAI,MAAM,CAAC,EAAE;QACpB,OAAO,MAAM,CAAC,EAAE,CAAC,KAAK,KAAK,UAAU,CACrC,CAAC;AACH,CAAC","sourcesContent":["import { I_WebsocketClient, I_WebsocketEntity, WebsocketStructuredMessage } from \"./websocket.types\";\nimport { type ServerWebSocket } from \"bun\";\n\nexport function IsWebsocketStructuredMessage(message: any): message is WebsocketStructuredMessage {\n\treturn typeof message === \"object\" && message !== null && \"type\" in message && \"content\" in message;\n}\n\nexport function IsWebsocketEntity(entity: any): entity is I_WebsocketEntity {\n\treturn (\n\t\ttypeof entity === \"object\" &&\n\t\tentity !== null &&\n\t\t\"id\" in entity &&\n\t\t\"name\" in entity &&\n\t\t\"ws\" in entity &&\n\t\ttypeof entity.ws === \"object\" &&\n\t\tentity.ws !== null &&\n\t\t\"send\" in entity.ws &&\n\t\ttypeof entity.ws.send === \"function\" &&\n\t\t\"close\" in entity.ws &&\n\t\ttypeof entity.ws.close === \"function\"\n\t);\n}\n"]}