topsyde-utils 1.3.2 → 2.0.1

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 (148) hide show
  1. package/dist/index.d.ts +2 -43
  2. package/dist/index.js +1 -38
  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/utils/index.d.ts +0 -3
  8. package/dist/utils/index.js +0 -3
  9. package/dist/utils/index.js.map +1 -1
  10. package/dist/websocket.shared.types.d.ts +25 -0
  11. package/dist/websocket.shared.types.js +4 -0
  12. package/dist/websocket.shared.types.js.map +1 -0
  13. package/package.json +12 -66
  14. package/src/__tests__/singleton.test.ts +0 -143
  15. package/src/index.ts +2 -83
  16. package/src/utils/Lib.ts +0 -77
  17. package/src/utils/index.ts +0 -3
  18. package/src/websocket.shared.types.ts +27 -0
  19. package/dist/application.d.ts +0 -18
  20. package/dist/application.js +0 -60
  21. package/dist/application.js.map +0 -1
  22. package/dist/client/api/base.api.d.ts +0 -63
  23. package/dist/client/api/base.api.js +0 -61
  24. package/dist/client/api/base.api.js.map +0 -1
  25. package/dist/client/api/index.d.ts +0 -2
  26. package/dist/client/api/index.js +0 -5
  27. package/dist/client/api/index.js.map +0 -1
  28. package/dist/client/rxjs/index.d.ts +0 -1
  29. package/dist/client/rxjs/index.js +0 -4
  30. package/dist/client/rxjs/index.js.map +0 -1
  31. package/dist/client/rxjs/useRxjs.d.ts +0 -17
  32. package/dist/client/rxjs/useRxjs.js +0 -87
  33. package/dist/client/rxjs/useRxjs.js.map +0 -1
  34. package/dist/client/vite/plugins/index.d.ts +0 -2
  35. package/dist/client/vite/plugins/index.js +0 -5
  36. package/dist/client/vite/plugins/index.js.map +0 -1
  37. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.d.ts +0 -9
  38. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.js +0 -74
  39. package/dist/client/vite/plugins/topsydeUtilsVitePlugin.js.map +0 -1
  40. package/dist/external/index.d.ts +0 -1
  41. package/dist/external/index.js +0 -4
  42. package/dist/external/index.js.map +0 -1
  43. package/dist/external/re-exports.d.ts +0 -16
  44. package/dist/external/re-exports.js +0 -24
  45. package/dist/external/re-exports.js.map +0 -1
  46. package/dist/server/base/base.database.d.ts +0 -10
  47. package/dist/server/base/base.database.js +0 -23
  48. package/dist/server/base/base.database.js.map +0 -1
  49. package/dist/server/base/index.d.ts +0 -2
  50. package/dist/server/base/index.js +0 -5
  51. package/dist/server/base/index.js.map +0 -1
  52. package/dist/server/bun/index.d.ts +0 -3
  53. package/dist/server/bun/index.js +0 -6
  54. package/dist/server/bun/index.js.map +0 -1
  55. package/dist/server/bun/router/controller-discovery.d.ts +0 -13
  56. package/dist/server/bun/router/controller-discovery.js +0 -83
  57. package/dist/server/bun/router/controller-discovery.js.map +0 -1
  58. package/dist/server/bun/router/index.d.ts +0 -6
  59. package/dist/server/bun/router/index.js +0 -9
  60. package/dist/server/bun/router/index.js.map +0 -1
  61. package/dist/server/bun/router/router.d.ts +0 -12
  62. package/dist/server/bun/router/router.internal.d.ts +0 -15
  63. package/dist/server/bun/router/router.internal.js +0 -51
  64. package/dist/server/bun/router/router.internal.js.map +0 -1
  65. package/dist/server/bun/router/router.js +0 -38
  66. package/dist/server/bun/router/router.js.map +0 -1
  67. package/dist/server/bun/router/routes.d.ts +0 -5
  68. package/dist/server/bun/router/routes.js +0 -2
  69. package/dist/server/bun/router/routes.js.map +0 -1
  70. package/dist/server/bun/websocket/Channel.d.ts +0 -68
  71. package/dist/server/bun/websocket/Channel.js +0 -263
  72. package/dist/server/bun/websocket/Channel.js.map +0 -1
  73. package/dist/server/bun/websocket/Client.d.ts +0 -87
  74. package/dist/server/bun/websocket/Client.js +0 -193
  75. package/dist/server/bun/websocket/Client.js.map +0 -1
  76. package/dist/server/bun/websocket/Message.d.ts +0 -10
  77. package/dist/server/bun/websocket/Message.js +0 -103
  78. package/dist/server/bun/websocket/Message.js.map +0 -1
  79. package/dist/server/bun/websocket/Websocket.d.ts +0 -171
  80. package/dist/server/bun/websocket/Websocket.js +0 -336
  81. package/dist/server/bun/websocket/Websocket.js.map +0 -1
  82. package/dist/server/bun/websocket/index.d.ts +0 -11
  83. package/dist/server/bun/websocket/index.js +0 -14
  84. package/dist/server/bun/websocket/index.js.map +0 -1
  85. package/dist/server/bun/websocket/websocket.enums.d.ts +0 -27
  86. package/dist/server/bun/websocket/websocket.enums.js +0 -31
  87. package/dist/server/bun/websocket/websocket.enums.js.map +0 -1
  88. package/dist/server/bun/websocket/websocket.guards.d.ts +0 -3
  89. package/dist/server/bun/websocket/websocket.guards.js +0 -17
  90. package/dist/server/bun/websocket/websocket.guards.js.map +0 -1
  91. package/dist/server/bun/websocket/websocket.types.d.ts +0 -235
  92. package/dist/server/bun/websocket/websocket.types.js +0 -2
  93. package/dist/server/bun/websocket/websocket.types.js.map +0 -1
  94. package/dist/server/controller.d.ts +0 -62
  95. package/dist/server/controller.js +0 -55
  96. package/dist/server/controller.js.map +0 -1
  97. package/dist/server/index.d.ts +0 -4
  98. package/dist/server/index.js +0 -7
  99. package/dist/server/index.js.map +0 -1
  100. package/dist/server/service.d.ts +0 -5
  101. package/dist/server/service.js +0 -38
  102. package/dist/server/service.js.map +0 -1
  103. package/dist/utils/BaseDto.d.ts +0 -33
  104. package/dist/utils/BaseDto.js +0 -69
  105. package/dist/utils/BaseDto.js.map +0 -1
  106. package/dist/utils/BaseEntity.d.ts +0 -31
  107. package/dist/utils/BaseEntity.js +0 -37
  108. package/dist/utils/BaseEntity.js.map +0 -1
  109. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.d.ts +0 -9
  110. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.js +0 -85
  111. package/dist/utils/dto_validators/IsNumberOrRangeConstraint.js.map +0 -1
  112. package/dist/utils/dto_validators/index.d.ts +0 -1
  113. package/dist/utils/dto_validators/index.js +0 -4
  114. package/dist/utils/dto_validators/index.js.map +0 -1
  115. package/src/__tests__/app.test.ts +0 -206
  116. package/src/application.ts +0 -73
  117. package/src/client/api/base.api.ts +0 -111
  118. package/src/client/api/index.ts +0 -5
  119. package/src/client/rxjs/index.ts +0 -4
  120. package/src/client/rxjs/useRxjs.ts +0 -113
  121. package/src/client/vite/plugins/index.ts +0 -5
  122. package/src/client/vite/plugins/topsydeUtilsVitePlugin.ts +0 -80
  123. package/src/external/index.ts +0 -4
  124. package/src/external/re-exports.ts +0 -54
  125. package/src/server/base/base.database.ts +0 -31
  126. package/src/server/base/index.ts +0 -5
  127. package/src/server/bun/index.ts +0 -6
  128. package/src/server/bun/router/controller-discovery.ts +0 -94
  129. package/src/server/bun/router/index.ts +0 -9
  130. package/src/server/bun/router/router.internal.ts +0 -64
  131. package/src/server/bun/router/router.ts +0 -51
  132. package/src/server/bun/router/routes.ts +0 -7
  133. package/src/server/bun/websocket/Channel.ts +0 -310
  134. package/src/server/bun/websocket/Client.ts +0 -243
  135. package/src/server/bun/websocket/ISSUES.md +0 -1175
  136. package/src/server/bun/websocket/Message.ts +0 -120
  137. package/src/server/bun/websocket/Websocket.ts +0 -402
  138. package/src/server/bun/websocket/index.ts +0 -14
  139. package/src/server/bun/websocket/websocket.enums.ts +0 -29
  140. package/src/server/bun/websocket/websocket.guards.ts +0 -22
  141. package/src/server/bun/websocket/websocket.types.ts +0 -252
  142. package/src/server/controller.ts +0 -121
  143. package/src/server/index.ts +0 -7
  144. package/src/server/service.ts +0 -36
  145. package/src/utils/BaseDto.ts +0 -77
  146. package/src/utils/BaseEntity.ts +0 -49
  147. package/src/utils/dto_validators/IsNumberOrRangeConstraint.ts +0 -32
  148. package/src/utils/dto_validators/index.ts +0 -4
@@ -1,120 +0,0 @@
1
- import Guards from "../../../utils/Guards";
2
- import { WebsocketStructuredMessage, WebsocketMessage, WebsocketMessageOptions, I_WebsocketClient, WebsocketEntityData } from "./websocket.types";
3
-
4
- export default class Message {
5
- // Shared template for all messages
6
- private static readonly MESSAGE_TEMPLATE: WebsocketStructuredMessage<any> = {
7
- type: "",
8
- content: {},
9
- channel: "",
10
- timestamp: "",
11
- };
12
-
13
- // Private constructor to prevent instantiation
14
- private constructor() {}
15
-
16
- public static Create(message: WebsocketMessage, options?: WebsocketMessageOptions): WebsocketStructuredMessage {
17
- // Clone the template
18
- const output = Object.assign({}, Message.MESSAGE_TEMPLATE);
19
-
20
- // Set the dynamic properties
21
- output.type = message.type;
22
- output.channel = message.channel || options?.channel || "N/A";
23
-
24
- // Process message content based on type
25
- if (typeof message.content === "string") {
26
- output.content = { message: message.content };
27
- } else if (typeof message.content === "object" && message.content !== null) {
28
- output.content = { ...message.content };
29
- } else {
30
- output.content = {};
31
- }
32
-
33
- // Process options if provided
34
- if (options) {
35
- // Add data if provided
36
- if (options.data !== undefined) {
37
- if (typeof options.data === "object" && options.data !== null && !Array.isArray(options.data)) {
38
- // Merge object data with content
39
- Object.assign(output.content, options.data);
40
- } else {
41
- // Set as data property for other types
42
- output.content.data = options.data;
43
- }
44
- }
45
-
46
- // Add client information if provided
47
- if (options.client && Guards.IsObject(options.client) && Guards.IsString(options.client.id, true)) {
48
- output.client = {
49
- id: options.client.id,
50
- name: options.client.name || "Unknown",
51
- };
52
- }
53
-
54
- // Include channel metadata if requested
55
- // Include channel metadata if provided as an object
56
- if (options.metadata && Guards.IsObject(options.metadata) && !Guards.IsArray(options.metadata)) {
57
- output.metadata = options.metadata;
58
- }
59
-
60
- // Add timestamp if requested (default: true)
61
- if (options.includeTimestamp !== false) {
62
- output.timestamp = new Date().toISOString();
63
- } else {
64
- // Remove timestamp if explicitly disabled
65
- delete output.timestamp;
66
- }
67
-
68
- // Add priority if specified
69
- if (options.priority !== undefined) {
70
- output.priority = options.priority;
71
- }
72
-
73
- // Add expiration if specified
74
- if (options.expiresAt !== undefined) {
75
- output.expiresAt = options.expiresAt;
76
- }
77
-
78
- // Add any custom fields to the root of the message
79
- if (options.customFields) {
80
- Object.assign(output, options.customFields);
81
- }
82
-
83
- // Apply custom transformation if provided
84
- if (options.transform) {
85
- return options.transform(output);
86
- }
87
- } else {
88
- output.timestamp = new Date().toISOString();
89
- }
90
-
91
- return output;
92
- }
93
-
94
- public static CreateWhisper(message: Omit<WebsocketMessage, "type">, options?: WebsocketMessageOptions): WebsocketStructuredMessage {
95
- return Message.Create({ ...message, content: message.content, channel: message.channel, type: "whisper" }, options);
96
- }
97
-
98
- public static Serialize<T = string>(message: WebsocketStructuredMessage, transform?: (message: WebsocketStructuredMessage) => T): string | T {
99
- return transform ? transform(message) : JSON.stringify(message);
100
- }
101
-
102
- public static Send(target: I_WebsocketClient, message: WebsocketMessage, options?: WebsocketMessageOptions): void {
103
- target.send(Message.Create(message, options));
104
- }
105
-
106
- public static Alert(target: I_WebsocketClient, reason: string, client?: WebsocketEntityData): void {
107
- target.send(
108
- Message.Create(
109
- {
110
- content: {
111
- message: reason,
112
- },
113
- channel: "alert",
114
- type: "message",
115
- },
116
- { client },
117
- ),
118
- );
119
- }
120
- }
@@ -1,402 +0,0 @@
1
- import { Server, ServerWebSocket, WebSocketHandler } from "bun";
2
- import Singleton from "../../../singleton";
3
- import { Lib } from "../../../utils";
4
- import { Console } from "../../../utils/Console";
5
- import Channel from "./Channel";
6
- import Client from "./Client";
7
- import type {
8
- I_WebsocketChannel,
9
- I_WebsocketClient,
10
- I_WebsocketEntity,
11
- I_WebsocketInterface,
12
- WebsocketChannel,
13
- WebsocketEntityData,
14
- BunWebsocketMessage,
15
- WebsocketStructuredMessage,
16
- } from "./websocket.types";
17
- import { E_WebsocketMessageType } from "./websocket.enums";
18
-
19
- export type WebsocketConstructorOptions = {
20
- debug?: boolean;
21
- global_channel_limit?: number;
22
- };
23
-
24
- export interface I_WebsocketConstructor {
25
- ws_interface?: I_WebsocketInterface;
26
- channels?: WebsocketChannel;
27
- clientClass?: typeof Client;
28
- channelClass?: typeof Channel;
29
- options?: WebsocketConstructorOptions;
30
- }
31
-
32
- /**
33
- * Websocket - Singleton managing clients, channels, and message routing
34
- *
35
- * ## API Design: Static vs Instance
36
- * - **Static methods**: Use in application code (e.g., `Websocket.Broadcast()`, `Websocket.GetClient()`)
37
- * - **Instance methods**: Use when extending the class (e.g., `protected createClient()`)
38
- *
39
- * Static methods are facades that call the singleton instance internally.
40
- *
41
- * @example
42
- * // Application code - use static methods
43
- * Websocket.Broadcast("lobby", { type: "chat", content: { message: "Hi!" } });
44
- *
45
- * // Extension - override instance methods
46
- * MyWebsocket extends Websocket:
47
- * protected createClient(entity) {
48
- * return new MyCustomClient(entity);
49
- * }
50
- */
51
- export default class Websocket extends Singleton {
52
- protected _channels: WebsocketChannel;
53
- protected _clients: Map<string, I_WebsocketClient> = new Map();
54
- protected _server!: Server;
55
- protected _channelClass: typeof Channel;
56
- protected _clientClass: typeof Client;
57
- protected _ws_interface?: I_WebsocketInterface;
58
- protected _options: WebsocketConstructorOptions;
59
- protected _ws_interface_handlers: Partial<WebSocketHandler<WebsocketEntityData>>;
60
- protected _lastId = 1;
61
-
62
- protected constructor(options?: I_WebsocketConstructor) {
63
- super();
64
- this._ws_interface = options?.ws_interface;
65
- this._channels = options?.channels ?? new Map<string, Channel>();
66
- this._clientClass = options?.clientClass ?? Client;
67
- this._channelClass = options?.channelClass ?? Channel.GetChannelType(options?.channels);
68
- this._options = options?.options ?? { debug: false };
69
- this.createChannel("global", "Global", this._options.global_channel_limit ?? 1000);
70
- this._ws_interface_handlers = this._ws_interface?.handlers(this._channels, this._clients) ?? {};
71
- }
72
-
73
- protected set server(value: Server) {
74
- this._server = value;
75
- }
76
-
77
- public get server(): Server {
78
- return this._server;
79
- }
80
-
81
- public set(server: Server) {
82
- this.server = server;
83
- Console.blank();
84
- Console.success("Websocket server set");
85
- }
86
-
87
- /**
88
- * Create a new channel
89
- * @param id - The id of the channel
90
- * @param name - The name of the channel
91
- * @param limit - The limit of the channel
92
- * @returns The created channel
93
- */
94
- public createChannel(id: string, name: string, limit?: number): Channel {
95
- if (this._channels.has(id)) return this._channels.get(id) as Channel;
96
- const channel = new this._channelClass(id, name, this, limit);
97
- this._channels.set(id, channel);
98
- return channel;
99
- }
100
-
101
- /**
102
- * Remove a channel
103
- * @param id - The id of the channel
104
- */
105
- public removeChannel(id: string) {
106
- const channel = this._channels.get(id);
107
- if (!channel) return;
108
- channel.delete();
109
- this._channels.delete(id);
110
- }
111
-
112
- /**
113
- * Create a new channel
114
- * @param id - The id of the channel
115
- * @param name - The name of the channel
116
- * @param limit - The limit of the channel
117
- * @returns The created channel
118
- */
119
- public static CreateChannel(id: string, name: string, limit?: number) {
120
- const ws = this.GetInstance<Websocket>();
121
- return ws.createChannel(id, name, limit);
122
- }
123
-
124
- public handlers(): WebSocketHandler<WebsocketEntityData> {
125
- return {
126
- open: this.clientConnected,
127
- message: this.clientMessageReceived,
128
- close: this.clientDisconnected,
129
- };
130
- }
131
-
132
- private clientMessageReceived = (ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) => {
133
- try {
134
- if (Websocket.Heartbeat(ws, message)) return;
135
-
136
- if (this._ws_interface_handlers.message) return this._ws_interface_handlers.message(ws, message);
137
-
138
- ws.send("This is the message from the server: " + message);
139
- Websocket.BroadCastAll({ type: "client.message.received", content: { message } });
140
- } catch (error) {
141
- console.error(error instanceof Error ? error.message : error);
142
- ws.close(1011, "Internal server error during message handling: " + (error instanceof Error ? error.message : error));
143
- }
144
- };
145
-
146
- private clientConnected = (ws: ServerWebSocket<WebsocketEntityData>) => {
147
- try {
148
- if (this._options.debug) Lib.Log("[debug] Client connected", ws.data);
149
-
150
- const global = this._channels.get("global");
151
- if (!global) throw new Error("Global channel not found");
152
-
153
- const client = Websocket.CreateClient({ id: ws.data.id, ws: ws, name: ws.data.name });
154
- this._clients.set(client.id, client);
155
- this._lastId++;
156
- if ((Number(client.id) || 0) >= this._lastId) this._lastId = Number(client.id) + 1;
157
-
158
- // Mark as fully connected
159
- client.markConnected();
160
-
161
- client.send({ type: E_WebsocketMessageType.CLIENT_CONNECTED, content: { message: "Welcome to the server", client: client.whoami() } });
162
-
163
- // Client handles its own joining logic with rollback support
164
- const joinResult = client.joinChannel(global);
165
- if (!joinResult.success) {
166
- throw new Error("Failed to join global channel: " + joinResult.reason);
167
- }
168
-
169
- if (this._ws_interface_handlers.open) this._ws_interface_handlers.open(ws);
170
- } catch (error) {
171
- console.error(error instanceof Error ? error.message : error);
172
- ws.close(1011, "Internal server error during connection setup: " + (error instanceof Error ? error.message : error));
173
- }
174
- };
175
-
176
- private clientDisconnected = (ws: ServerWebSocket<WebsocketEntityData>, code: number, reason: string) => {
177
- try {
178
- if (this._options.debug) Lib.Log("Client disconnected", ws.data);
179
-
180
- const client = this._clients.get(ws.data.id);
181
- if (!client) return;
182
-
183
- // Mark as disconnecting
184
- client.markDisconnecting();
185
-
186
- if (this._ws_interface_handlers.close) this._ws_interface_handlers.close(ws, code, reason);
187
-
188
- // Remove from all channels
189
- this._channels.forEach((channel) => {
190
- channel.removeMember(client);
191
- });
192
-
193
- // Remove from registry
194
- this._clients.delete(ws.data.id);
195
- // Mark as disconnected
196
- client.markDisconnected();
197
- } catch (error) {
198
- console.error(error instanceof Error ? error.message : error);
199
- ws.close(1011, "Internal server error during disconnection: " + (error instanceof Error ? error.message : error));
200
- }
201
- };
202
-
203
- private handleHeartbeat = (ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) => {
204
- if (message === "ping") {
205
- const pong: WebsocketStructuredMessage = { type: "pong", content: { message: "pong" } };
206
- ws.send(JSON.stringify(pong));
207
- return true;
208
- }
209
- return false;
210
- };
211
-
212
- protected createClient(entity: I_WebsocketEntity): I_WebsocketClient {
213
- return new this._clientClass(entity);
214
- }
215
-
216
- /**
217
- * Handle the heartbeat
218
- * @param ws - The websocket
219
- * @param message - The message
220
- * @returns True if the heartbeat was handled, false otherwise
221
- */
222
- public static Heartbeat(ws: ServerWebSocket<WebsocketEntityData>, message: BunWebsocketMessage) {
223
- const self = this.GetInstance<Websocket>();
224
- return self.handleHeartbeat(ws, message);
225
- }
226
-
227
- /**
228
- * Get the server
229
- * @returns The server
230
- */
231
- public static Server() {
232
- return this.GetInstance<Websocket>().server;
233
- }
234
-
235
- /**
236
- * Broadcast a message to a channel
237
- * @param channel - The channel
238
- * @param message - The message
239
- * @param args - The arguments
240
- */
241
- public static Broadcast(channel: string, message: WebsocketStructuredMessage, ...args: any[]) {
242
- // Get the server from the singleton instance
243
- const ws = this.GetInstance<Websocket>();
244
- if (!ws.server) {
245
- throw new Error("Websocket server not set");
246
- }
247
- ws.server.publish(channel, JSON.stringify({ message, args }));
248
- }
249
-
250
- /**
251
- * Broadcast a message to all channels
252
- * @param message - The message
253
- * @param args - The arguments
254
- */
255
- public static BroadCastAll(message: WebsocketStructuredMessage, ...args: any[]) {
256
- const ws = this.GetInstance<Websocket>();
257
- ws._channels.forEach((channel) => channel.broadcast(message, ...args));
258
- }
259
-
260
- /**
261
- * Join a channel
262
- * @param channel - The channel
263
- * @param entity - The entity
264
- */
265
- public static Join(channel: string, entity: I_WebsocketEntity) {
266
- const ws = this.GetInstance<Websocket>();
267
- const client = ws._clients.get(entity.id);
268
- if (!client) return;
269
- ws._channels.get(channel)?.addMember(client);
270
- }
271
-
272
- /**
273
- * Leave a channel
274
- * @param channel - The channel
275
- * @param entity - The entity
276
- */
277
- public static Leave(channel: string, entity: I_WebsocketEntity) {
278
- const ws = this.GetInstance<Websocket>();
279
- const client = ws._clients.get(entity.id);
280
- if (!client) return;
281
- ws._channels.get(channel)?.removeMember(client);
282
- }
283
-
284
- /**
285
- * Get a client
286
- * @param id - The id of the client
287
- * @param throw_if_nil - Whether to throw an error if the client is not found
288
- * @returns The client
289
- */
290
- public static GetClient(id: string, throw_if_nil?: true): I_WebsocketClient;
291
- public static GetClient(id: string, throw_if_nil?: false): I_WebsocketClient | undefined;
292
- public static GetClient(id: string, throw_if_nil: boolean = true): I_WebsocketClient | undefined {
293
- const ws = this.GetInstance<Websocket>();
294
- const client = ws._clients.get(id);
295
- if (!client && throw_if_nil) throw new Error(`Client with id ${id} not found`);
296
- return client;
297
- }
298
-
299
- /**
300
- * Get a channel
301
- * @param id - The id of the channel
302
- * @returns The channel
303
- */
304
- public static GetChannel(id: string) {
305
- const ws = this.GetInstance<Websocket>();
306
- return ws._channels.get(id);
307
- }
308
-
309
- /**
310
- * Get all channels
311
- * @returns The channels
312
- */
313
- public static GetChannels() {
314
- const ws = this.GetInstance<Websocket>();
315
- return Array.from(ws._channels.values());
316
- }
317
-
318
- /**
319
- * Get all clients
320
- * @returns The clients
321
- */
322
- public static GetClients() {
323
- const ws = this.GetInstance<Websocket>();
324
- return Array.from(ws._clients.values());
325
- }
326
-
327
- public static GetLastId() {
328
- const ws = this.GetInstance<Websocket>();
329
- return ws._lastId;
330
- }
331
-
332
- /**
333
- * Get the number of clients
334
- * @returns The number of clients
335
- */
336
- public static GetClientCount() {
337
- const ws = this.GetInstance<Websocket>();
338
- return ws._clients.size;
339
- }
340
-
341
- /**
342
- * Get the number of channels
343
- * @returns The number of channels
344
- */
345
- public static GetChannelCount() {
346
- const ws = this.GetInstance<Websocket>();
347
- return ws._channels.size;
348
- }
349
-
350
- /**
351
- * Create a client
352
- * @param entity - The entity
353
- * @returns The created client
354
- */
355
- public static CreateClient(entity: I_WebsocketEntity): I_WebsocketClient {
356
- const ws = this.GetInstance<Websocket>();
357
- return ws.createClient(entity);
358
- }
359
-
360
- /**
361
- * Get all connected clients (excluding connecting/disconnecting)
362
- * @returns Array of connected clients
363
- */
364
- public static GetConnectedClients(): I_WebsocketClient[] {
365
- const ws = this.GetInstance<Websocket>();
366
- return Array.from(ws._clients.values()).filter((client) => client.state === "connected");
367
- }
368
-
369
- /**
370
- * Get client statistics by state
371
- * @returns Object with counts by state
372
- */
373
- public static GetClientStats() {
374
- const ws = this.GetInstance<Websocket>();
375
- const stats = {
376
- total: ws._clients.size,
377
- connecting: 0,
378
- connected: 0,
379
- disconnecting: 0,
380
- disconnected: 0,
381
- };
382
-
383
- for (const client of ws._clients.values()) {
384
- switch (client.state) {
385
- case "connecting":
386
- stats.connecting++;
387
- break;
388
- case "connected":
389
- stats.connected++;
390
- break;
391
- case "disconnecting":
392
- stats.disconnecting++;
393
- break;
394
- case "disconnected":
395
- stats.disconnected++;
396
- break;
397
- }
398
- }
399
-
400
- return stats;
401
- }
402
- }
@@ -1,14 +0,0 @@
1
- // This file is auto-generated by scripts/generate-indexes.ts
2
- // Do not edit this file directly
3
-
4
- export * from './Websocket';
5
- export * from './websocket.guards';
6
- export * from './Message';
7
- export * from './Channel';
8
- export * from './Client';
9
- export * from './websocket.enums';
10
- export * from './websocket.types';
11
- export { default as Websocket } from './Websocket';
12
- export { default as Message } from './Message';
13
- export { default as Channel } from './Channel';
14
- export { default as Client } from './Client';
@@ -1,29 +0,0 @@
1
- export 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
-
18
- export enum E_WebsocketMessagePriority {
19
- LOW = 0,
20
- MEDIUM = 1,
21
- HIGH = 2,
22
- }
23
-
24
- export enum E_ClientState {
25
- CONNECTING = "connecting",
26
- CONNECTED = "connected",
27
- DISCONNECTING = "disconnecting",
28
- DISCONNECTED = "disconnected",
29
- }
@@ -1,22 +0,0 @@
1
- import { I_WebsocketClient, I_WebsocketEntity, WebsocketStructuredMessage } from "./websocket.types";
2
- import { type ServerWebSocket } from "bun";
3
-
4
- export function IsWebsocketStructuredMessage(message: any): message is WebsocketStructuredMessage {
5
- return typeof message === "object" && message !== null && "type" in message && "content" in message;
6
- }
7
-
8
- export function IsWebsocketEntity(entity: any): entity is I_WebsocketEntity {
9
- return (
10
- typeof entity === "object" &&
11
- entity !== null &&
12
- "id" in entity &&
13
- "name" in entity &&
14
- "ws" in entity &&
15
- typeof entity.ws === "object" &&
16
- entity.ws !== null &&
17
- "send" in entity.ws &&
18
- typeof entity.ws.send === "function" &&
19
- "close" in entity.ws &&
20
- typeof entity.ws.close === "function"
21
- );
22
- }