topsyde-utils 1.2.1 → 1.2.3

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.
@@ -2,7 +2,7 @@ import { Server, ServerWebSocket, WebSocketHandler } from "bun";
2
2
  import Singleton from "../../../singleton";
3
3
  import Channel from "./Channel";
4
4
  import Client from "./Client";
5
- import type { I_WebsocketChannel, I_WebsocketClient, I_WebsocketEntity, I_WebsocketInterface, WebsocketChannel, WebsocketEntityData, BunWebsocketMessage, WebsocketStructuredMessage } from "./websocket.types";
5
+ import type { I_WebsocketClient, I_WebsocketEntity, I_WebsocketInterface, WebsocketChannel, WebsocketEntityData, BunWebsocketMessage, WebsocketStructuredMessage } from "./websocket.types";
6
6
  export type WebsocketConstructorOptions = {
7
7
  debug?: boolean;
8
8
  global_channel_limit?: number;
@@ -54,7 +54,7 @@ export default class Websocket extends Singleton {
54
54
  * @param limit - The limit of the channel
55
55
  * @returns The created channel
56
56
  */
57
- createChannel(id: string, name: string, limit?: number): I_WebsocketChannel;
57
+ createChannel(id: string, name: string, limit?: number): Channel;
58
58
  /**
59
59
  * Remove a channel
60
60
  * @param id - The id of the channel
@@ -67,7 +67,7 @@ export default class Websocket extends Singleton {
67
67
  * @param limit - The limit of the channel
68
68
  * @returns The created channel
69
69
  */
70
- static CreateChannel(id: string, name: string, limit?: number): I_WebsocketChannel<Websocket>;
70
+ static CreateChannel(id: string, name: string, limit?: number): Channel<Websocket>;
71
71
  handlers(): WebSocketHandler<WebsocketEntityData>;
72
72
  private clientMessageReceived;
73
73
  private clientConnected;
@@ -1 +1 @@
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): I_WebsocketChannel {\n\t\tif (this._channels.has(id)) return this._channels.get(id) as I_WebsocketChannel;\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\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
+ {"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\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"]}
@@ -18,8 +18,8 @@ export default abstract class Controller extends Initializable {
18
18
  static Create<T>(this: new () => T): T;
19
19
  static AsyncCreate<T>(this: new () => T): Promise<T>;
20
20
  call<T>(request: Request): Promise<T>;
21
- success<T>(data: T, after_action?: Function): I_ApplicationResponse<T>;
22
- failure<T>(data: T, after_action?: Function): I_ApplicationResponse<T>;
21
+ success<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T>;
22
+ failure<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T>;
23
23
  private setControllerMap;
24
24
  private resolve;
25
25
  private resolveAction;
@@ -1 +1 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/server/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,aAAuC,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAclC,MAAM,CAAC,OAAO,OAAgB,UAAW,SAAQ,aAAa;IAM7D;QACC,KAAK,EAAE,CAAC;QALT,SAAI,GAAuC,IAAI,GAAG,EAAE,CAAC;QACrD,QAAG,GAAkB,IAAI,GAAG,EAAE,CAAC;QAC/B,kBAAa,GAA+B,IAAI,GAAG,EAAE,CAAC;QAIrD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACzB,CAAC;IAEM,MAAM,CAAC,MAAM;QACnB,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,WAAW;QAC9B,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,IAAI,CAAI,OAAgB;QACpC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAuB;QACjD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC7C,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAuB;QACjD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9C,CAAC;IAEO,gBAAgB;QACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAEO,OAAO,CAAC,GAAY;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;YAAE,MAAM,UAAU,CAAC,cAAc,CAAC;QAExE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAErD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,cAAc,CAAC;QACjC,CAAC;QAED,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,SAAwB,EAAE,UAAkB;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,CAAa,CAAC;QAErD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,UAAU,CAAC,gBAAgB,CAAC;QACnC,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CAuCD","sourcesContent":["import { ERROR_CODE } from \"../errors\";\nimport Initializable, { InitializableOptions } from \"../initializable\";\nimport { I_ApplicationResponse } from \"../types\";\nimport { Guards } from \"../utils\";\n\nexport type ControllerResponse<T = unknown> = Promise<I_ApplicationResponse<T> | PromiseLike<I_ApplicationResponse<T>>>;\nexport type ControllerAction<T> = (req: Request) => ControllerResponse<T>;\n\nexport type ControllerMap<T = unknown> = Map<string, ControllerAction<T>>;\n\nexport type ControllerOptions<T = unknown> = InitializableOptions & {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<T>>;\n\tget: ControllerMap<T>;\n\tcontrollerMap: Map<string, ControllerMap<T>>;\n};\n\nexport default abstract class Controller extends Initializable {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<any>> = new Map();\n\tget: ControllerMap = new Map();\n\tcontrollerMap: Map<string, ControllerMap> = new Map();\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.POST();\n\t\tthis.GET();\n\t\tthis.setControllerMap();\n\t}\n\n\tpublic static Create<T>(this: new () => T): T {\n\t\treturn new this();\n\t}\n\n\tpublic static async AsyncCreate<T>(this: new () => T): Promise<T> {\n\t\treturn new this();\n\t}\n\n\tpublic async call<T>(request: Request): Promise<T> {\n\t\tawait this.isInitialized();\n\t\tconst action = this.resolve(request);\n\t\treturn await action(request);\n\t}\n\n\tpublic success<T>(data: T, after_action?: Function): I_ApplicationResponse<T> {\n\t\treturn { status: true, data, after_action };\n\t}\n\n\tpublic failure<T>(data: T, after_action?: Function): I_ApplicationResponse<T> {\n\t\treturn { status: false, data, after_action };\n\t}\n\n\tprivate setControllerMap() {\n\t\tthis.controllerMap.set(\"GET\", this.get);\n\t\tthis.controllerMap.set(\"POST\", this.post);\n\t}\n\n\tprivate resolve(req: Request): Function {\n\t\tconst url = new URL(req.url);\n\t\tconst endpointArray = url.pathname.split(\"/\");\n\t\tconst actionName = endpointArray.slice(2).join(\"/\");\n\n\t\tif (!Guards.IsString(actionName, true)) throw ERROR_CODE.INVALID_ACTION;\n\n\t\tconst methodMap = this.controllerMap.get(req.method);\n\n\t\tif (Guards.IsNil(methodMap)) {\n\t\t\tthrow ERROR_CODE.INVALID_METHOD;\n\t\t}\n\n\t\treturn this.resolveAction(methodMap, actionName);\n\t}\n\n\tprivate resolveAction(methodMap: ControllerMap, actionName: string) {\n\t\tconst action = methodMap.get(actionName) as Function;\n\n\t\tif (!Guards.IsFunction(action, true)) {\n\t\t\tthrow ERROR_CODE.NO_ACTION_IN_MAP;\n\t\t}\n\n\t\treturn action;\n\t}\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map post actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.post.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract POST(): void;\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.get.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract GET(): void;\n}\n"]}
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/server/controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,aAAuC,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAclC,MAAM,CAAC,OAAO,OAAgB,UAAW,SAAQ,aAAa;IAM7D;QACC,KAAK,EAAE,CAAC;QALT,SAAI,GAAuC,IAAI,GAAG,EAAE,CAAC;QACrD,QAAG,GAAkB,IAAI,GAAG,EAAE,CAAC;QAC/B,kBAAa,GAA+B,IAAI,GAAG,EAAE,CAAC;QAIrD,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,GAAG,EAAE,CAAC;QACX,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACzB,CAAC;IAEM,MAAM,CAAC,MAAM;QACnB,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,WAAW;QAC9B,OAAO,IAAI,IAAI,EAAE,CAAC;IACnB,CAAC;IAEM,KAAK,CAAC,IAAI,CAAI,OAAgB;QACpC,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAyC;QACnE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC7C,CAAC;IAEM,OAAO,CAAI,IAAO,EAAE,YAAyC;QACnE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9C,CAAC;IAEO,gBAAgB;QACvB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAEO,OAAO,CAAC,GAAY;QAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;YAAE,MAAM,UAAU,CAAC,cAAc,CAAC;QAExE,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAErD,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,cAAc,CAAC;QACjC,CAAC;QAED,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,SAAwB,EAAE,UAAkB;QACjE,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,UAAU,CAAa,CAAC;QAErD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,UAAU,CAAC,gBAAgB,CAAC;QACnC,CAAC;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CAuCD","sourcesContent":["import { ERROR_CODE } from \"../errors\";\nimport Initializable, { InitializableOptions } from \"../initializable\";\nimport { I_ApplicationResponse } from \"../types\";\nimport { Guards } from \"../utils\";\n\nexport type ControllerResponse<T = unknown> = Promise<I_ApplicationResponse<T> | PromiseLike<I_ApplicationResponse<T>>>;\nexport type ControllerAction<T> = (req: Request) => ControllerResponse<T>;\n\nexport type ControllerMap<T = unknown> = Map<string, ControllerAction<T>>;\n\nexport type ControllerOptions<T = unknown> = InitializableOptions & {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<T>>;\n\tget: ControllerMap<T>;\n\tcontrollerMap: Map<string, ControllerMap<T>>;\n};\n\nexport default abstract class Controller extends Initializable {\n\tpath: string | undefined;\n\tpost: Map<string, ControllerAction<any>> = new Map();\n\tget: ControllerMap = new Map();\n\tcontrollerMap: Map<string, ControllerMap> = new Map();\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.POST();\n\t\tthis.GET();\n\t\tthis.setControllerMap();\n\t}\n\n\tpublic static Create<T>(this: new () => T): T {\n\t\treturn new this();\n\t}\n\n\tpublic static async AsyncCreate<T>(this: new () => T): Promise<T> {\n\t\treturn new this();\n\t}\n\n\tpublic async call<T>(request: Request): Promise<T> {\n\t\tawait this.isInitialized();\n\t\tconst action = this.resolve(request);\n\t\treturn await action(request);\n\t}\n\n\tpublic success<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {\n\t\treturn { status: true, data, after_action };\n\t}\n\n\tpublic failure<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {\n\t\treturn { status: false, data, after_action };\n\t}\n\n\tprivate setControllerMap() {\n\t\tthis.controllerMap.set(\"GET\", this.get);\n\t\tthis.controllerMap.set(\"POST\", this.post);\n\t}\n\n\tprivate resolve(req: Request): Function {\n\t\tconst url = new URL(req.url);\n\t\tconst endpointArray = url.pathname.split(\"/\");\n\t\tconst actionName = endpointArray.slice(2).join(\"/\");\n\n\t\tif (!Guards.IsString(actionName, true)) throw ERROR_CODE.INVALID_ACTION;\n\n\t\tconst methodMap = this.controllerMap.get(req.method);\n\n\t\tif (Guards.IsNil(methodMap)) {\n\t\t\tthrow ERROR_CODE.INVALID_METHOD;\n\t\t}\n\n\t\treturn this.resolveAction(methodMap, actionName);\n\t}\n\n\tprivate resolveAction(methodMap: ControllerMap, actionName: string) {\n\t\tconst action = methodMap.get(actionName) as Function;\n\n\t\tif (!Guards.IsFunction(action, true)) {\n\t\t\tthrow ERROR_CODE.NO_ACTION_IN_MAP;\n\t\t}\n\n\t\treturn action;\n\t}\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map post actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.post.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract POST(): void;\n\n\t/**\n\t * Abstract method that needs to be implemented in derived classes.\n\t * This method is used to map actions to their corresponding handler methods.\n\t *\n\t * Each action is a string that represents a specific operation, and the handler is a function that performs this operation.\n\t * The handler is bound to the current context (`this`) to ensure it has access to the class's properties and methods.\n\t *\n\t * Example implementation:\n\t *\n\t * ```typescript\n\t * setActionsMap() {\n\t * this.get.set(\"action\", this.controllerMethod.bind(this));\n\t * }\n\t * ```\n\t *\n\t * In this example, when \"https://webserver_url:port/controller/action\" is called by the router, the `controllerMethod` method will be called.\n\t */\n\tabstract GET(): void;\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -10,6 +10,7 @@ export interface I_ApplicationResponse<T = unknown> {
10
10
  status: boolean | number;
11
11
  data: T;
12
12
  error?: T;
13
- after_action?: Function;
13
+ after_action?: () => void | Promise<void>;
14
+ before_action?: () => void;
14
15
  }
15
16
  export {};
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type ClassConstructor<T> = new (...args: any[]) => T;\nexport type NonNullableType<T> = Exclude<T, null | undefined>;\ntype ObjectKeysValues = string | number | string[] | number[] | null;\nexport type ObjectKeys<T, U = ObjectKeysValues> = Partial<Record<keyof T, U>>;\nexport type KVObj<T> = { key: string; value: T };\nexport interface I_ApplicationResponse<T = unknown> {\n\tstatus: boolean | number;\n\tdata: T;\n\terror?: T;\n\tafter_action?: Function;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export type ClassConstructor<T> = new (...args: any[]) => T;\nexport type NonNullableType<T> = Exclude<T, null | undefined>;\ntype ObjectKeysValues = string | number | string[] | number[] | null;\nexport type ObjectKeys<T, U = ObjectKeysValues> = Partial<Record<keyof T, U>>;\nexport type KVObj<T> = { key: string; value: T };\nexport interface I_ApplicationResponse<T = unknown> {\n\tstatus: boolean | number;\n\tdata: T;\n\terror?: T;\n\tafter_action?: () => void | Promise<void>;\n\tbefore_action?: () => void;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topsyde-utils",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "A bundle of TypeScript utility classes and functions",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -91,8 +91,8 @@ export default class Websocket extends Singleton {
91
91
  * @param limit - The limit of the channel
92
92
  * @returns The created channel
93
93
  */
94
- public createChannel(id: string, name: string, limit?: number): I_WebsocketChannel {
95
- if (this._channels.has(id)) return this._channels.get(id) as I_WebsocketChannel;
94
+ public createChannel(id: string, name: string, limit?: number): Channel {
95
+ if (this._channels.has(id)) return this._channels.get(id) as Channel;
96
96
  const channel = new this._channelClass(id, name, this, limit);
97
97
  this._channels.set(id, channel);
98
98
  return channel;
@@ -42,11 +42,11 @@ export default abstract class Controller extends Initializable {
42
42
  return await action(request);
43
43
  }
44
44
 
45
- public success<T>(data: T, after_action?: Function): I_ApplicationResponse<T> {
45
+ public success<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {
46
46
  return { status: true, data, after_action };
47
47
  }
48
48
 
49
- public failure<T>(data: T, after_action?: Function): I_ApplicationResponse<T> {
49
+ public failure<T>(data: T, after_action?: () => void | Promise<void>): I_ApplicationResponse<T> {
50
50
  return { status: false, data, after_action };
51
51
  }
52
52
 
package/src/types.ts CHANGED
@@ -7,5 +7,6 @@ export interface I_ApplicationResponse<T = unknown> {
7
7
  status: boolean | number;
8
8
  data: T;
9
9
  error?: T;
10
- after_action?: Function;
10
+ after_action?: () => void | Promise<void>;
11
+ before_action?: () => void;
11
12
  }