@scpxl/nodejs-framework 1.0.17 → 1.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/api-requester/api-requester.d.ts +27 -6
- package/dist/api-requester/api-requester.d.ts.map +1 -1
- package/dist/api-requester/api-requester.js +188 -26
- package/dist/api-requester/api-requester.js.map +2 -2
- package/dist/api-requester/index.d.ts +1 -0
- package/dist/api-requester/index.d.ts.map +1 -1
- package/dist/api-requester/index.js.map +1 -1
- package/dist/application/base-application.d.ts +15 -22
- package/dist/application/base-application.d.ts.map +1 -1
- package/dist/application/base-application.js +145 -111
- package/dist/application/base-application.js.map +2 -2
- package/dist/application/command-application.d.ts.map +1 -1
- package/dist/application/command-application.js +3 -4
- package/dist/application/command-application.js.map +2 -2
- package/dist/application/web-application.d.ts.map +1 -1
- package/dist/application/web-application.js +9 -2
- package/dist/application/web-application.js.map +2 -2
- package/dist/cache/manager.d.ts +87 -6
- package/dist/cache/manager.d.ts.map +1 -1
- package/dist/cache/manager.js +77 -30
- package/dist/cache/manager.js.map +2 -2
- package/dist/cluster/cluster-manager.d.ts.map +1 -1
- package/dist/cluster/cluster-manager.js +5 -8
- package/dist/cluster/cluster-manager.js.map +2 -2
- package/dist/config/env.d.ts +11 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +103 -0
- package/dist/config/env.js.map +7 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +3 -0
- package/dist/config/index.js.map +7 -0
- package/dist/config/schema.d.ts +408 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +218 -0
- package/dist/config/schema.js.map +7 -0
- package/dist/database/dynamic-entity.d.ts.map +1 -1
- package/dist/database/dynamic-entity.js +6 -2
- package/dist/database/dynamic-entity.js.map +2 -2
- package/dist/database/instance.d.ts.map +1 -1
- package/dist/database/instance.js +0 -8
- package/dist/database/instance.js.map +2 -2
- package/dist/database/manager.d.ts.map +1 -1
- package/dist/database/manager.js +71 -9
- package/dist/database/manager.js.map +2 -2
- package/dist/error/error-reporter.d.ts +96 -0
- package/dist/error/error-reporter.d.ts.map +1 -0
- package/dist/error/error-reporter.js +228 -0
- package/dist/error/error-reporter.js.map +7 -0
- package/dist/error/error.interface.d.ts +126 -0
- package/dist/error/error.interface.d.ts.map +1 -0
- package/dist/error/error.interface.js +45 -0
- package/dist/error/error.interface.js.map +7 -0
- package/dist/error/framework-errors.d.ts +113 -0
- package/dist/error/framework-errors.d.ts.map +1 -0
- package/dist/error/framework-errors.js +176 -0
- package/dist/error/framework-errors.js.map +7 -0
- package/dist/error/index.d.ts +6 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +34 -0
- package/dist/error/index.js.map +7 -0
- package/dist/event/manager.d.ts.map +1 -1
- package/dist/event/manager.js +2 -9
- package/dist/event/manager.js.map +2 -2
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +2 -2
- package/dist/lifecycle/exit.d.ts +2 -1
- package/dist/lifecycle/exit.d.ts.map +1 -1
- package/dist/lifecycle/exit.js +6 -0
- package/dist/lifecycle/exit.js.map +2 -2
- package/dist/lifecycle/index.d.ts +7 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +12 -0
- package/dist/lifecycle/index.js.map +7 -0
- package/dist/lifecycle/lifecycle-manager.d.ts +55 -2
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-manager.js +233 -7
- package/dist/lifecycle/lifecycle-manager.js.map +3 -3
- package/dist/lifecycle/shutdown-controller.d.ts +15 -0
- package/dist/lifecycle/shutdown-controller.d.ts.map +1 -0
- package/dist/lifecycle/shutdown-controller.js +38 -0
- package/dist/lifecycle/shutdown-controller.js.map +7 -0
- package/dist/lifecycle/types.d.ts +28 -0
- package/dist/lifecycle/types.d.ts.map +1 -0
- package/dist/lifecycle/types.js +13 -0
- package/dist/lifecycle/types.js.map +7 -0
- package/dist/logger/logger.d.ts +2 -1
- package/dist/logger/logger.d.ts.map +1 -1
- package/dist/logger/logger.js +35 -11
- package/dist/logger/logger.js.map +2 -2
- package/dist/performance/cache-performance.d.ts +6 -0
- package/dist/performance/cache-performance.d.ts.map +1 -1
- package/dist/performance/cache-performance.js +16 -0
- package/dist/performance/cache-performance.js.map +2 -2
- package/dist/performance/index.d.ts +1 -0
- package/dist/performance/index.d.ts.map +1 -1
- package/dist/performance/index.js +1 -0
- package/dist/performance/index.js.map +2 -2
- package/dist/performance/performance-monitor.d.ts.map +1 -1
- package/dist/performance/performance-monitor.js +47 -18
- package/dist/performance/performance-monitor.js.map +2 -2
- package/dist/performance/performance-monitor.plugin.d.ts +24 -0
- package/dist/performance/performance-monitor.plugin.d.ts.map +1 -0
- package/dist/performance/performance-monitor.plugin.js +89 -0
- package/dist/performance/performance-monitor.plugin.js.map +7 -0
- package/dist/performance/webserver-performance.js +1 -1
- package/dist/performance/webserver-performance.js.map +2 -2
- package/dist/queue/manager.d.ts.map +1 -1
- package/dist/queue/manager.js +3 -10
- package/dist/queue/manager.js.map +2 -2
- package/dist/queue/worker.d.ts.map +1 -1
- package/dist/queue/worker.js +2 -2
- package/dist/queue/worker.js.map +2 -2
- package/dist/redis/manager.d.ts.map +1 -1
- package/dist/redis/manager.js +228 -33
- package/dist/redis/manager.js.map +2 -2
- package/dist/request-context/index.d.ts +3 -0
- package/dist/request-context/index.d.ts.map +1 -0
- package/dist/request-context/index.js +25 -0
- package/dist/request-context/index.js.map +7 -0
- package/dist/request-context/request-context.d.ts +108 -0
- package/dist/request-context/request-context.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.d.ts +46 -0
- package/dist/request-context/request-context.interface.d.ts.map +1 -0
- package/dist/request-context/request-context.interface.js +1 -0
- package/dist/request-context/request-context.interface.js.map +7 -0
- package/dist/request-context/request-context.js +79 -0
- package/dist/request-context/request-context.js.map +7 -0
- package/dist/services/aws/s3.js +4 -6
- package/dist/services/aws/s3.js.map +2 -2
- package/dist/util/file.d.ts +13 -0
- package/dist/util/file.d.ts.map +1 -1
- package/dist/util/file.js +46 -9
- package/dist/util/file.js.map +2 -2
- package/dist/util/helper.d.ts +16 -1
- package/dist/util/helper.d.ts.map +1 -1
- package/dist/util/helper.js +19 -43
- package/dist/util/helper.js.map +2 -2
- package/dist/util/index.d.ts +1 -0
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +18 -16
- package/dist/util/index.js.map +2 -2
- package/dist/util/loader.d.ts.map +1 -1
- package/dist/util/loader.js +13 -2
- package/dist/util/loader.js.map +2 -2
- package/dist/util/os.d.ts.map +1 -1
- package/dist/util/os.js +8 -14
- package/dist/util/os.js.map +2 -2
- package/dist/util/time.d.ts +8 -2
- package/dist/util/time.d.ts.map +1 -1
- package/dist/util/time.js +12 -7
- package/dist/util/time.js.map +2 -2
- package/dist/util/timing.d.ts +36 -0
- package/dist/util/timing.d.ts.map +1 -0
- package/dist/util/timing.interface.d.ts +47 -0
- package/dist/util/timing.interface.d.ts.map +1 -0
- package/dist/util/timing.interface.js +1 -0
- package/dist/util/timing.interface.js.map +7 -0
- package/dist/util/timing.js +98 -0
- package/dist/util/timing.js.map +7 -0
- package/dist/util/url.js +1 -1
- package/dist/util/url.js.map +2 -2
- package/dist/webserver/controller/base.d.ts +3 -1
- package/dist/webserver/controller/base.d.ts.map +1 -1
- package/dist/webserver/controller/base.interface.d.ts +2 -0
- package/dist/webserver/controller/base.interface.d.ts.map +1 -1
- package/dist/webserver/controller/base.js +4 -1
- package/dist/webserver/controller/base.js.map +2 -2
- package/dist/webserver/controller/health.d.ts +8 -1
- package/dist/webserver/controller/health.d.ts.map +1 -1
- package/dist/webserver/controller/health.js +36 -22
- package/dist/webserver/controller/health.js.map +2 -2
- package/dist/webserver/webserver.d.ts +16 -2
- package/dist/webserver/webserver.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.d.ts +37 -0
- package/dist/webserver/webserver.interface.d.ts.map +1 -1
- package/dist/webserver/webserver.interface.js.map +2 -2
- package/dist/webserver/webserver.js +117 -20
- package/dist/webserver/webserver.js.map +2 -2
- package/dist/websocket/controllers/server/system.d.ts.map +1 -1
- package/dist/websocket/controllers/server/system.js.map +2 -2
- package/dist/websocket/websocket-base.d.ts.map +1 -1
- package/dist/websocket/websocket-base.js +2 -3
- package/dist/websocket/websocket-base.js.map +2 -2
- package/dist/websocket/websocket-server.d.ts +1 -1
- package/dist/websocket/websocket-server.d.ts.map +1 -1
- package/dist/websocket/websocket-server.js +7 -31
- package/dist/websocket/websocket-server.js.map +2 -2
- package/package.json +51 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/websocket/websocket-server.ts"],
|
|
4
|
-
"sourcesContent": ["import { type RawData, WebSocketServer as WS, WebSocket } from 'ws';\nimport {\n type WebSocketOptions,\n WebSocketRedisSubscriberEvent,\n type WebSocketRoute,\n type WebSocketType,\n} from './websocket.interface.js';\nimport type RedisInstance from '../redis/instance.js';\nimport type QueueManager from '../queue/manager.js';\nimport type DatabaseInstance from '../database/instance.js';\nimport type { WebSocketServerProps } from './websocket-server.interface.js';\nimport WebSocketClientManager from './websocket-client-manager.js';\nimport { generateClientId, log } from './utils.js';\nimport WebSocketBase from './websocket-base.js';\nimport { Logger } from '../logger/index.js';\nimport path from 'path';\nimport { type WebApplicationConfig, baseDir } from '../index.js';\nimport WebSocketRoomManager from './websocket-room-manager.js';\nimport logger from '../logger/logger.js';\nimport type { FastifyInstance } from 'fastify';\nimport { URL } from 'url';\nimport Jwt from '../auth/jwt.js';\n\nexport default class WebSocketServer extends WebSocketBase {\n protected defaultRoutes: WebSocketRoute[] = [\n {\n type: 'system',\n action: 'joinRoom',\n controllerName: 'system',\n },\n {\n type: 'system',\n action: 'leaveRoom',\n controllerName: 'system',\n },\n ];\n\n private server?: WS;\n\n private checkConnectedClientsInterval?: ReturnType<typeof setInterval>;\n private workerId: number | null;\n private uniqueInstanceId: string;\n private applicationConfig: WebApplicationConfig;\n private options: WebSocketOptions;\n public clientManager = new WebSocketClientManager();\n private roomManager = new WebSocketRoomManager({\n clientManager: this.clientManager,\n });\n\n public get rooms() {\n return this.roomManager.rooms;\n }\n private redisInstance: RedisInstance;\n private queueManager: QueueManager;\n private databaseInstance: DatabaseInstance;\n\n /** Redis subscriber events */\n private redisSubscriberEvents: string[] = [\n WebSocketRedisSubscriberEvent.ClientConnected,\n WebSocketRedisSubscriberEvent.ClientJoinedRoom,\n WebSocketRedisSubscriberEvent.ClientLeftRoom,\n WebSocketRedisSubscriberEvent.ClientDisconnected,\n WebSocketRedisSubscriberEvent.DisconnectClient,\n WebSocketRedisSubscriberEvent.SendMessage,\n WebSocketRedisSubscriberEvent.SendMessageToAll,\n WebSocketRedisSubscriberEvent.MessageError,\n WebSocketRedisSubscriberEvent.QueueJobCompleted,\n WebSocketRedisSubscriberEvent.QueueJobError,\n WebSocketRedisSubscriberEvent.Custom,\n ];\n\n constructor(props: WebSocketServerProps) {\n super();\n\n this.uniqueInstanceId = props.uniqueInstanceId;\n this.applicationConfig = props.applicationConfig;\n this.options = props.options;\n this.redisInstance = props.redisInstance;\n this.queueManager = props.queueManager;\n this.databaseInstance = props.databaseInstance;\n this.routes = props.routes;\n this.workerId = props.workerId;\n }\n\n public get type(): WebSocketType {\n return 'server';\n }\n\n private async validateWebSocketAuth(url: string): Promise<{ userId: number; payload: any } | null> {\n try {\n const parsedUrl = new URL(url, 'ws://localhost');\n const token = parsedUrl.searchParams.get('token');\n\n if (!token) {\n return null; // No token provided, allow unauthenticated connection\n }\n\n // Get JWT secret key from application config\n const jwtSecretKey = this.applicationConfig.auth?.jwtSecretKey;\n\n if (!jwtSecretKey) {\n throw new Error('JWT secret key not configured');\n }\n\n // Import JWT secret key\n const importedJwtSecretKey = await Jwt.importJwtSecretKey({\n jwtSecretKey,\n });\n\n // Verify JWT token\n const { payload } = await Jwt.jwtVerify(token, importedJwtSecretKey);\n\n const userId = parseInt(payload.sub as string);\n\n if (isNaN(userId)) {\n throw new Error('Invalid user ID in token');\n }\n\n return { userId, payload };\n } catch (error: any) {\n throw new Error(`JWT verification failed: ${error.message}`);\n }\n }\n\n public async load(): Promise<void> {\n const libraryControllersDirectory = path.join(baseDir, 'websocket', 'controllers', 'server');\n\n // Configure default routes\n await this.configureRoutes(this.defaultRoutes, libraryControllersDirectory);\n\n // Configure custom routes\n await this.configureRoutes(this.routes, this.options.controllersDirectory);\n }\n\n public async start({ fastifyServer }: { fastifyServer: FastifyInstance }): Promise<{ server: WS }> {\n return new Promise(resolve => {\n const server = new WS({\n noServer: true, // We're handling the server externally\n });\n\n this.server = server;\n\n // Ensure this is called after the server has been properly set up\n this.handleServerStart();\n\n fastifyServer.server.on('upgrade', async (request, socket, head) => {\n if (request.url?.startsWith('/ws')) {\n try {\n // Validate authentication token if provided\n const authenticatedUser = await this.validateWebSocketAuth(request.url);\n\n server.handleUpgrade(request, socket, head, ws => {\n server.emit('connection', ws, request, authenticatedUser);\n });\n } catch (error: any) {\n log('WebSocket authentication failed', { error: error.message });\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n }\n } else {\n socket.destroy();\n }\n });\n\n server.on('error', this.handleServerError);\n\n server.on(\n 'connection',\n (ws: WebSocket, request: any, authenticatedUser: { userId: number; payload: any } | null) => {\n this.handleServerClientConnection(ws, authenticatedUser);\n },\n );\n\n // Resolve the promise with the server instance\n resolve({ server });\n });\n }\n\n public async stop(): Promise<void> {\n if (this.checkConnectedClientsInterval) {\n clearInterval(this.checkConnectedClientsInterval);\n this.checkConnectedClientsInterval = undefined;\n }\n\n // Clean up Redis subscriber listeners\n this.redisInstance.subscriberClient?.removeListener('message', this.handleSubscriberMessage);\n\n // Unsubscribe from all Redis events\n this.redisSubscriberEvents.forEach(subscriberEventName => {\n this.redisInstance.subscriberClient?.unsubscribe(subscriberEventName);\n });\n\n // Close all client connections and clean up\n if (this.server) {\n this.server.clients.forEach(client => {\n client.removeAllListeners();\n client.close();\n });\n\n this.server.removeAllListeners();\n this.server.close();\n }\n\n // Clean up client manager and room manager\n this.clientManager.cleanup();\n this.roomManager.cleanup();\n\n // Reset managers\n this.clientManager = new WebSocketClientManager();\n this.roomManager = new WebSocketRoomManager({\n clientManager: this.clientManager,\n });\n\n log('Server stopped');\n }\n\n protected getControllerDependencies(): {\n webSocketServer: WebSocketServer;\n redisInstance: RedisInstance;\n queueManager: QueueManager;\n databaseInstance: DatabaseInstance;\n } {\n return {\n webSocketServer: this,\n redisInstance: this.redisInstance,\n queueManager: this.queueManager,\n databaseInstance: this.databaseInstance,\n };\n }\n\n protected shouldPrintRoutes(): boolean {\n return this.options.debug?.printRoutes ?? false;\n }\n\n private handleServerStart = (): void => {\n if (!this.server) {\n throw new Error('WebSocket server not started');\n }\n\n if (this.options.disconnectInactiveClients?.enabled) {\n this.checkConnectedClientsInterval = setInterval(\n () => this.checkInactiveClients(),\n this.options.disconnectInactiveClients.intervalCheckTime,\n );\n }\n\n // Go through each event and subscribe to it\n this.redisSubscriberEvents.forEach(subscriberEventName => {\n // Subscribe to event\n this.redisInstance.subscriberClient?.subscribe(subscriberEventName);\n });\n\n // Handle subscriber message\n this.redisInstance.subscriberClient.on('message', this.handleSubscriberMessage);\n\n log('Server started', {\n Host: this.options.host,\n URL: this.options.url,\n });\n\n if (this.options.events?.onServerStarted) {\n this.options.events.onServerStarted({\n webSocketServer: this.server,\n });\n }\n };\n\n /**\n * Handle subscriber message.\n */\n private handleSubscriberMessage = async (channel: string, message: string): Promise<void> => {\n let parsedMessage: { [key: string]: any };\n\n try {\n parsedMessage = JSON.parse(message);\n } catch (error) {\n log('Failed to parse subscriber message', {\n Channel: channel,\n Message: message,\n Error: error,\n });\n\n return;\n }\n\n const runSameWorker = parsedMessage.runSameWorker === true;\n\n const isSameWorker = parsedMessage.workerId === this.workerId;\n\n // Check if message is from the same worker\n if (runSameWorker !== true && isSameWorker) {\n // Ignore the message if it's from the same worker\n return;\n }\n\n log('Incoming subscriber message', {\n Channel: channel,\n // 'Run Same Worker': parsedMessage.runSameWorker ? 'Yes' : 'No',\n 'Client ID': parsedMessage.clientId ?? '-',\n });\n\n switch (channel) {\n case WebSocketRedisSubscriberEvent.ClientConnected: {\n this.onClientConnect({\n clientId: parsedMessage.clientId,\n lastActivity: parsedMessage.lastActivity,\n user: parsedMessage.user,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientDisconnected: {\n this.onClientDisconnect({\n clientId: parsedMessage.clientId,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.DisconnectClient: {\n const clientToDisconnect = this.clientManager.getClient({\n clientId: parsedMessage.clientId,\n // requireWs: true,\n });\n\n log(\n `GOT A REQUEST TO POTENTIALLY DISCONNECT LCIENT IF THIS CLIENT IS CONNETED HERE, GET CLIENT ------------------------- ${clientToDisconnect ?? 'NO CLIENT'}`,\n );\n\n console.log('clientToDisconnect', clientToDisconnect, 'workerId: ', this.workerId);\n\n if (clientToDisconnect) {\n this.clientManager.disconnectClient({\n clientId: parsedMessage.clientId,\n });\n\n // this.onClientDisconnect({\n // clientId: parsedMessage.clientId,\n // });\n\n // Remove client from rooms\n this.roomManager.removeClientFromAllRooms({\n clientId: parsedMessage.clientId,\n });\n }\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientJoinedRoom: {\n this.onJoinRoom({\n clientId: parsedMessage.clientId,\n roomName: parsedMessage.roomName,\n userData: parsedMessage.user,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientLeftRoom: {\n this.roomManager.removeClientFromRoom({\n roomName: parsedMessage.room,\n clientId: parsedMessage.clientId,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.SendMessage: {\n break;\n }\n case WebSocketRedisSubscriberEvent.SendMessageToAll: {\n this.broadcastToAllClients({ data: parsedMessage });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.MessageError: {\n this.sendMessageError({\n webSocketClientId: parsedMessage.clientId,\n error: parsedMessage.error,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.QueueJobCompleted: {\n // const parsedMessage = JSON.parse(message);\n\n // this.sendJobDoneMessage({ type: 'jobCompleted', ...parsedMessage });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.QueueJobError: {\n // const parsedMessage = JSON.parse(message);\n\n // action and data is separate\n // TODO: Instead allow to pass anything\n parsedMessage.data = parsedMessage.error;\n\n // this.sendJobDoneMessage({ type: 'jobError', ...parsedMessage });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.Custom: {\n // Custom logic is being handled in the app\n\n break;\n }\n default: {\n log('Unknown subscriber message received', {\n Channel: channel,\n Message: message,\n });\n }\n }\n\n if (typeof this.applicationConfig.webSocket?.subscriberEventHandler === 'function') {\n // Execute custom application subscriber event handler\n this.applicationConfig.webSocket.subscriberEventHandler({\n channel,\n message: parsedMessage,\n webSocketServer: this,\n databaseInstance: this.databaseInstance,\n });\n }\n };\n\n private handleServerError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private handleServerClientConnection = (\n ws: WebSocket,\n authenticatedUser?: { userId: number; payload: any } | null,\n ): void => {\n const clientId = generateClientId();\n\n const lastActivity = Date.now();\n\n ws.on('message', (message: RawData) => this.handleClientMessage(ws, message));\n\n ws.on('close', () => {\n this.handleServerClientDisconnection(clientId);\n this.clientManager.removeClient(clientId);\n\n // Clean up event listeners to prevent memory leaks\n ws.removeAllListeners();\n });\n\n try {\n this.clientManager.addClient({\n clientId,\n ws,\n lastActivity,\n user: authenticatedUser,\n });\n\n // Let other workers know that the client has connected\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientConnected,\n JSON.stringify({\n clientId,\n lastActivity,\n workerId: this.workerId,\n user: authenticatedUser,\n }),\n );\n\n // Send authentication success message if user is authenticated\n if (authenticatedUser) {\n this.sendClientMessage(ws, {\n type: 'auth',\n action: 'authenticated',\n data: {\n userId: authenticatedUser.userId,\n message: 'Authentication successful',\n },\n });\n }\n } catch (error) {\n logger.error({ error });\n }\n };\n\n public leaveRoom({ ws, roomName }: { ws: WebSocket; roomName: string }): void {\n const clientId = this.clientManager.getClientId({ ws });\n\n if (!clientId) {\n log('Client ID not found when removing client from room');\n\n return;\n }\n\n // Check if client is in room\n const clientInRoom = this.roomManager.isClientInRoom({\n clientId,\n roomName,\n });\n\n if (!clientInRoom) {\n log('Client not in room when removing client from room', {\n 'Client ID': clientId || '-',\n 'Room Name': roomName,\n });\n\n return;\n }\n\n this.roomManager.removeClientFromRoom({\n roomName,\n clientId,\n });\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientLeftRoom,\n JSON.stringify({\n clientId,\n room: roomName,\n workerId: this.workerId,\n }),\n );\n\n // Optionally send a message to the client\n this.sendClientMessage(ws, {\n type: 'user',\n action: 'leftRoom',\n data: {\n roomName,\n },\n });\n }\n\n private onClientConnect({\n clientId,\n lastActivity,\n user,\n }: {\n clientId: string;\n lastActivity: number;\n user?: { userId: number; payload: any } | null;\n }): void {\n this.clientManager.addClient({\n clientId,\n ws: null,\n lastActivity,\n user,\n });\n }\n\n private onClientDisconnect({ clientId }: { clientId: string }): void {\n // Set client as disconnected\n this.clientManager.removeClient(clientId);\n\n // Remove client from rooms\n this.roomManager.removeClientFromAllRooms({ clientId });\n }\n\n private handleServerClientDisconnection = (clientId: string): void => {\n const client = this.clientManager.getClient({\n clientId,\n });\n\n if (!client) {\n log('Client not found when handling server client disconnection', {\n 'Client ID': clientId || '-',\n });\n\n return;\n }\n\n this.onClientDisconnect({ clientId });\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientDisconnected,\n JSON.stringify({\n clientId,\n workerId: this.workerId,\n }),\n );\n\n // log('Client disconnected', { ID: clientId });\n };\n\n private handleClientMessage = async (ws: WebSocket, message: RawData): Promise<void> => {\n try {\n const clientId = this.clientManager.getClientId({\n ws,\n });\n\n if (!clientId) {\n log('Client ID not found when handling server message');\n\n return;\n }\n\n // Handle server message\n const serverMessageResponse = await this.handleServerMessage(ws, message, clientId);\n\n if (serverMessageResponse) {\n this.sendClientMessage(ws, {\n type: serverMessageResponse.type,\n action: serverMessageResponse.action,\n response: serverMessageResponse?.response,\n });\n\n if (serverMessageResponse?.response?.error) {\n // throw new Error(serverMessageResponse?.response?.error);\n\n Logger.error({ error: serverMessageResponse.response.error });\n }\n }\n } catch (error) {\n Logger.error({ error });\n\n log('Error handling client message', {\n Error: error,\n });\n }\n };\n\n protected handleMessageError(clientId: string, error: string): void {\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.MessageError,\n JSON.stringify({\n runSameWorker: true,\n clientId,\n error,\n }),\n );\n }\n\n private checkInactiveClients(): void {\n // const now = Date.now();\n\n if (this.options.disconnectInactiveClients?.enabled && this.options.disconnectInactiveClients.log) {\n log('Checking inactive clients...');\n }\n\n // const numInactiveClients = 0;\n\n // this.connectedClients.forEach(\n // (clientInfo, clientId) => {\n // if (\n // this.options.disconnectInactiveClients?.enabled &&\n // typeof this.options.disconnectInactiveClients\n // .inactiveTime === 'number'\n // ) {\n // const timeUntilInactive = Math.max(\n // 0,\n // this.options.disconnectInactiveClients\n // .inactiveTime -\n // (now - clientInfo.lastActivity),\n // );\n // const isClientInactive = timeUntilInactive <= 0;\n\n // if (this.options.disconnectInactiveClients.log) {\n // log('Checking client activity', {\n // ID: clientId,\n // 'Time Until Inactive': Time.formatTime({\n // time: timeUntilInactive,\n // format: 'auto',\n // }),\n // });\n // }\n\n // if (isClientInactive) {\n // this.disconnectClient({ clientId });\n\n // numInactiveClients++;\n // }\n // }\n // },\n // );\n\n // if (\n // this.options.disconnectInactiveClients?.enabled &&\n // this.options.disconnectInactiveClients.log\n // ) {\n // if (numInactiveClients > 0) {\n // log('Inactive clients disconnected', {\n // Count: numInactiveClients,\n // });\n // } else {\n // log('No inactive clients');\n // }\n // }\n }\n\n // private disconnectClient({\n // clientId,\n // }: {\n // clientId: string;\n // }) {\n // const clientInfo = this.connectedClients.get(clientId);\n\n // if (clientInfo?.ws) {\n // const connectedTime =\n // Date.now() - clientInfo.lastActivity;\n\n // clientInfo.ws.close();\n\n // Logger.info(\n // 'WebSocket client was disconnected due to inactivity',\n // {\n // ID: clientId,\n // Worker: this.workerId,\n // 'Time Connected': Time.formatTime({\n // time: connectedTime,\n // format: 's',\n // }),\n // },\n // );\n // }\n // }\n\n public broadcastToAllClients({\n data,\n excludeClientId,\n }: {\n data: { [key: string]: any };\n excludeClientId?: string;\n }): void {\n if (!this.server) {\n log('Server not started when broadcasting to all clients');\n\n return;\n }\n\n this.server.clients.forEach(client => {\n let excludeClient = false;\n\n if (excludeClientId) {\n const clientId = this.clientManager.getClientId({\n ws: client,\n });\n\n excludeClient = clientId === excludeClientId;\n }\n\n if (client.readyState === WebSocket.OPEN && !excludeClient) {\n client.send(JSON.stringify(data));\n }\n });\n }\n\n public sendMessageError({ webSocketClientId, error }: { webSocketClientId: string; error: string }): void {\n const client = this.clientManager.getClient({\n clientId: webSocketClientId,\n });\n\n if (!client) {\n log('Client not found when sending message error', {\n 'Client ID': webSocketClientId || '-',\n Error: error,\n });\n\n return;\n } else if (!client.ws) {\n log('Client WebSocket not found when sending message error', {\n 'Client ID': webSocketClientId || '-',\n Error: error,\n });\n\n return;\n }\n\n this.sendClientMessage(client.ws, {\n type: 'error',\n action: 'message',\n data: {\n error,\n },\n });\n }\n\n // private getClientId({\n // client,\n // }: {\n // client: WebSocket;\n // }): string | undefined {\n // return [...this.connectedClients.entries()].find(\n // ([_, value]) => value.ws === client,\n // )?.[0];\n // }\n\n private onJoinRoom({ clientId, roomName, userData }: { clientId: string; roomName: string; userData: any }): void {\n // TODO: If config clientCanJoinMultipleRooms !== true, then it should remove the user from existing room first\n const client = this.clientManager.getClient({\n clientId,\n });\n\n if (!client) {\n log('Client not found when joining room', {\n 'Client ID': clientId || '-',\n 'Room Name': roomName,\n });\n\n return;\n }\n\n const clientCanJoinMultipleRooms: any = false;\n\n if (clientCanJoinMultipleRooms !== true) {\n if (client.roomName) {\n // Remove client from current room\n this.roomManager.removeClientFromRoom({\n roomName: client.roomName,\n clientId,\n });\n }\n }\n\n // Update client with user in client manager\n this.clientManager.updateClient({\n clientId,\n key: 'user',\n data: userData,\n });\n\n this.roomManager.addClientToRoom({\n clientId,\n user: userData,\n roomName,\n });\n }\n\n public async joinRoom({\n ws,\n userId,\n userType,\n username,\n roomName,\n }: {\n ws: WebSocket;\n userId?: number;\n userType?: string;\n username?: string;\n roomName: string;\n }) {\n const clientId = this.clientManager.getClientId({ ws });\n\n if (!clientId) {\n // throw new Error('Client ID not found when joining room');\n\n logger.warn({\n message: 'Client ID not found when joining room',\n meta: {\n // 'WebSocket ID': ws?.id || '-',\n 'Room Name': roomName,\n },\n });\n\n return;\n }\n\n // Check if client is already in room\n const isClientInRoom = this.roomManager.isClientInRoom({\n clientId,\n roomName,\n });\n\n if (isClientInRoom) {\n // throw new Error('Client already in room when joining');\n\n logger.warn({\n message: 'Client already in room when joining',\n meta: {\n // 'WebSocket ID': ws?. || '-',\n 'Room Name': roomName,\n 'Client ID': clientId,\n },\n });\n\n return;\n }\n\n let userData: any = {};\n\n // // Get WebSocket client ID\n // const webSocketId = this.clientManager.getClientId({ ws });\n\n if (userId) {\n // Get user email from database\n const dbEntityManager = this.databaseInstance.getEntityManager();\n\n const getUserQuery = 'SELECT email FROM users WHERE id = ?';\n const getUserParams = [userId];\n\n const getUserResult = await dbEntityManager.execute(getUserQuery, getUserParams);\n\n if (!getUserResult || getUserResult.length === 0) {\n throw new Error('User not found in database');\n }\n\n const user = getUserResult[0];\n\n userData = {\n id: userId,\n ...user,\n };\n }\n\n // userData.uniqueId = webSocketId;\n\n if (username) {\n userData.username = username;\n }\n\n userData.userType = userType;\n\n // if user with same email is already connected, disconnect the previous connection\n // const existingClient =\n // this.clientManager.getClientByKey({\n // key: 'user.email',\n // value: user.email,\n // });\n\n // if (existingClient) {\n // if (existingClient.ws) {\n // this.clientManager.disconnectClient({\n // clientId: existingClient.clientId,\n // });\n // } else {\n // // Publish to Redis that we should disconnect this client\n // this.redisInstance.publisherClient.publish(\n // WebSocketRedisSubscriberEvent.DisconnectClient,\n // JSON.stringify({\n // clientId,\n // workerId: this.workerId,\n // }),\n // );\n // }\n // }\n\n this.onJoinRoom({\n clientId,\n roomName,\n userData,\n });\n\n // Let other workers know that the client has joined the room\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientJoinedRoom,\n JSON.stringify({\n clientId,\n user: userData,\n roomName,\n workerId: this.workerId,\n }),\n );\n\n return true;\n }\n\n public sendClientMessage = (ws: WebSocket, data: unknown, binary: boolean = false): void => {\n const webSocketMessage = JSON.stringify(data);\n\n ws.send(webSocketMessage, { binary });\n };\n\n public sendMessage = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.SendMessage,\n JSON.stringify(formattedData),\n );\n };\n\n public sendMessageToAll = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.SendMessageToAll,\n JSON.stringify(formattedData),\n );\n };\n\n public sendCustomMessage = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n console.log('SEND CUSTOM MESSAGE:', formattedData);\n\n this.redisInstance.publisherClient.publish(WebSocketRedisSubscriberEvent.Custom, JSON.stringify(formattedData));\n };\n\n public getClients({ userType }: { userType?: string }): any[] {\n return this.clientManager.getClients({ userType });\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { type RawData, WebSocketServer as WS, WebSocket } from 'ws';\nimport {\n type WebSocketOptions,\n WebSocketRedisSubscriberEvent,\n type WebSocketRoute,\n type WebSocketType,\n} from './websocket.interface.js';\nimport type RedisInstance from '../redis/instance.js';\nimport type QueueManager from '../queue/manager.js';\nimport type DatabaseInstance from '../database/instance.js';\nimport type { WebSocketServerProps } from './websocket-server.interface.js';\nimport WebSocketClientManager from './websocket-client-manager.js';\nimport { generateClientId, log } from './utils.js';\nimport WebSocketBase from './websocket-base.js';\nimport { Logger } from '../logger/index.js';\nimport path from 'path';\nimport { type WebApplicationConfig, baseDir } from '../index.js';\nimport WebSocketRoomManager from './websocket-room-manager.js';\nimport logger from '../logger/logger.js';\nimport type { FastifyInstance } from 'fastify';\nimport { URL } from 'url';\nimport Jwt from '../auth/jwt.js';\n\nexport default class WebSocketServer extends WebSocketBase {\n protected defaultRoutes: WebSocketRoute[] = [\n {\n type: 'system',\n action: 'joinRoom',\n controllerName: 'system',\n },\n {\n type: 'system',\n action: 'leaveRoom',\n controllerName: 'system',\n },\n ];\n\n private server?: WS;\n\n private abortController = new AbortController();\n private workerId: number | null;\n private uniqueInstanceId: string;\n private applicationConfig: WebApplicationConfig;\n private options: WebSocketOptions;\n public clientManager = new WebSocketClientManager();\n private roomManager = new WebSocketRoomManager({\n clientManager: this.clientManager,\n });\n\n public get rooms() {\n return this.roomManager.rooms;\n }\n private redisInstance: RedisInstance;\n private queueManager: QueueManager;\n private databaseInstance: DatabaseInstance;\n\n /** Redis subscriber events */\n private redisSubscriberEvents: string[] = [\n WebSocketRedisSubscriberEvent.ClientConnected,\n WebSocketRedisSubscriberEvent.ClientJoinedRoom,\n WebSocketRedisSubscriberEvent.ClientLeftRoom,\n WebSocketRedisSubscriberEvent.ClientDisconnected,\n WebSocketRedisSubscriberEvent.DisconnectClient,\n WebSocketRedisSubscriberEvent.SendMessage,\n WebSocketRedisSubscriberEvent.SendMessageToAll,\n WebSocketRedisSubscriberEvent.MessageError,\n WebSocketRedisSubscriberEvent.QueueJobCompleted,\n WebSocketRedisSubscriberEvent.QueueJobError,\n WebSocketRedisSubscriberEvent.Custom,\n ];\n\n constructor(props: WebSocketServerProps) {\n super();\n\n this.uniqueInstanceId = props.uniqueInstanceId;\n this.applicationConfig = props.applicationConfig;\n this.options = props.options;\n this.redisInstance = props.redisInstance;\n this.queueManager = props.queueManager;\n this.databaseInstance = props.databaseInstance;\n this.routes = props.routes;\n this.workerId = props.workerId;\n }\n\n public get type(): WebSocketType {\n return 'server';\n }\n\n private async validateWebSocketAuth(url: string): Promise<{ userId: number; payload: any } | null> {\n try {\n const parsedUrl = new URL(url, 'ws://localhost');\n const token = parsedUrl.searchParams.get('token');\n\n if (!token) {\n return null; // No token provided, allow unauthenticated connection\n }\n\n // Get JWT secret key from application config\n const jwtSecretKey = this.applicationConfig.auth?.jwtSecretKey;\n\n if (!jwtSecretKey) {\n throw new Error('JWT secret key not configured');\n }\n\n // Import JWT secret key\n const importedJwtSecretKey = await Jwt.importJwtSecretKey({\n jwtSecretKey,\n });\n\n // Verify JWT token\n const { payload } = await Jwt.jwtVerify(token, importedJwtSecretKey);\n\n const userId = parseInt(payload.sub as string);\n\n if (isNaN(userId)) {\n throw new Error('Invalid user ID in token');\n }\n\n return { userId, payload };\n } catch (error: any) {\n throw new Error(`JWT verification failed: ${error.message}`);\n }\n }\n\n public async load(): Promise<void> {\n const libraryControllersDirectory = path.join(baseDir, 'websocket', 'controllers', 'server');\n\n // Configure default routes\n await this.configureRoutes(this.defaultRoutes, libraryControllersDirectory);\n\n // Configure custom routes\n await this.configureRoutes(this.routes, this.options.controllersDirectory);\n }\n\n public async start({ fastifyServer }: { fastifyServer: FastifyInstance }): Promise<{ server: WS }> {\n return new Promise(resolve => {\n const server = new WS({\n noServer: true, // We're handling the server externally\n });\n\n this.server = server;\n\n // Ensure this is called after the server has been properly set up\n this.handleServerStart();\n\n fastifyServer.server.on('upgrade', async (request, socket, head) => {\n if (request.url?.startsWith('/ws')) {\n try {\n // Validate authentication token if provided\n const authenticatedUser = await this.validateWebSocketAuth(request.url);\n\n server.handleUpgrade(request, socket, head, ws => {\n server.emit('connection', ws, request, authenticatedUser);\n });\n } catch (error: any) {\n log('WebSocket authentication failed', { error: error.message });\n socket.write('HTTP/1.1 401 Unauthorized\\r\\n\\r\\n');\n socket.destroy();\n }\n } else {\n socket.destroy();\n }\n });\n\n server.on('error', this.handleServerError);\n\n server.on(\n 'connection',\n (ws: WebSocket, request: any, authenticatedUser: { userId: number; payload: any } | null) => {\n this.handleServerClientConnection(ws, authenticatedUser);\n },\n );\n\n // Resolve the promise with the server instance\n resolve({ server });\n });\n }\n\n public async stop(): Promise<void> {\n // Abort all ongoing operations (intervals, etc.)\n this.abortController.abort();\n\n // Clean up Redis subscriber listeners\n this.redisInstance.subscriberClient?.removeListener('message', this.handleSubscriberMessage);\n\n // Unsubscribe from all Redis events\n this.redisSubscriberEvents.forEach(subscriberEventName => {\n this.redisInstance.subscriberClient?.unsubscribe(subscriberEventName);\n });\n\n // Close all client connections and clean up\n if (this.server) {\n this.server.clients.forEach(client => {\n client.removeAllListeners();\n client.close();\n });\n\n this.server.removeAllListeners();\n this.server.close();\n }\n\n // Clean up client manager and room manager\n this.clientManager.cleanup();\n this.roomManager.cleanup();\n\n // Reset managers\n this.clientManager = new WebSocketClientManager();\n this.roomManager = new WebSocketRoomManager({\n clientManager: this.clientManager,\n });\n\n // Create new AbortController for potential restart\n this.abortController = new AbortController();\n\n log('Server stopped');\n }\n\n protected getControllerDependencies(): {\n webSocketServer: WebSocketServer;\n redisInstance: RedisInstance;\n queueManager: QueueManager;\n databaseInstance: DatabaseInstance;\n } {\n return {\n webSocketServer: this,\n redisInstance: this.redisInstance,\n queueManager: this.queueManager,\n databaseInstance: this.databaseInstance,\n };\n }\n\n protected shouldPrintRoutes(): boolean {\n return this.options.debug?.printRoutes ?? false;\n }\n\n private handleServerStart = (): void => {\n if (!this.server) {\n throw new Error('WebSocket server not started');\n }\n\n if (this.options.disconnectInactiveClients?.enabled && this.options.disconnectInactiveClients.intervalCheckTime) {\n // Note: setInterval with signal option requires Node.js 15+\n // TypeScript types may not reflect this, so we use type assertion\n (setInterval as (fn: () => void, ms: number, options?: { signal: AbortSignal }) => NodeJS.Timeout)(\n () => this.checkInactiveClients(),\n this.options.disconnectInactiveClients.intervalCheckTime,\n { signal: this.abortController.signal },\n );\n }\n\n // Go through each event and subscribe to it\n this.redisSubscriberEvents.forEach(subscriberEventName => {\n // Subscribe to event\n this.redisInstance.subscriberClient?.subscribe(subscriberEventName);\n });\n\n // Handle subscriber message\n this.redisInstance.subscriberClient.on('message', this.handleSubscriberMessage);\n\n log('Server started', {\n Host: this.options.host,\n URL: this.options.url,\n });\n\n if (this.options.events?.onServerStarted) {\n this.options.events.onServerStarted({\n webSocketServer: this.server,\n });\n }\n };\n\n /**\n * Handle subscriber message.\n */\n private handleSubscriberMessage = async (channel: string, message: string): Promise<void> => {\n let parsedMessage: { [key: string]: any };\n\n try {\n parsedMessage = JSON.parse(message);\n } catch (error) {\n log('Failed to parse subscriber message', {\n Channel: channel,\n Message: message,\n Error: error,\n });\n\n return;\n }\n\n const runSameWorker = parsedMessage.runSameWorker === true;\n\n const isSameWorker = parsedMessage.workerId === this.workerId;\n\n // Check if message is from the same worker\n if (runSameWorker !== true && isSameWorker) {\n // Ignore the message if it's from the same worker\n return;\n }\n\n log('Incoming subscriber message', {\n Channel: channel,\n // 'Run Same Worker': parsedMessage.runSameWorker ? 'Yes' : 'No',\n 'Client ID': parsedMessage.clientId ?? '-',\n });\n\n switch (channel) {\n case WebSocketRedisSubscriberEvent.ClientConnected: {\n this.onClientConnect({\n clientId: parsedMessage.clientId,\n lastActivity: parsedMessage.lastActivity,\n user: parsedMessage.user,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientDisconnected: {\n this.onClientDisconnect({\n clientId: parsedMessage.clientId,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.DisconnectClient: {\n const clientToDisconnect = this.clientManager.getClient({\n clientId: parsedMessage.clientId,\n // requireWs: true,\n });\n\n log(\n `GOT A REQUEST TO POTENTIALLY DISCONNECT LCIENT IF THIS CLIENT IS CONNETED HERE, GET CLIENT ------------------------- ${clientToDisconnect ?? 'NO CLIENT'}`,\n );\n\n console.log('clientToDisconnect', clientToDisconnect, 'workerId: ', this.workerId);\n\n if (clientToDisconnect) {\n this.clientManager.disconnectClient({\n clientId: parsedMessage.clientId,\n });\n\n // Remove client from rooms\n this.roomManager.removeClientFromAllRooms({\n clientId: parsedMessage.clientId,\n });\n }\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientJoinedRoom: {\n this.onJoinRoom({\n clientId: parsedMessage.clientId,\n roomName: parsedMessage.roomName,\n userData: parsedMessage.user,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.ClientLeftRoom: {\n this.roomManager.removeClientFromRoom({\n roomName: parsedMessage.room,\n clientId: parsedMessage.clientId,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.SendMessage: {\n break;\n }\n case WebSocketRedisSubscriberEvent.SendMessageToAll: {\n this.broadcastToAllClients({ data: parsedMessage });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.MessageError: {\n this.sendMessageError({\n webSocketClientId: parsedMessage.clientId,\n error: parsedMessage.error,\n });\n\n break;\n }\n case WebSocketRedisSubscriberEvent.QueueJobCompleted: {\n // const parsedMessage = JSON.parse(message);\n\n break;\n }\n case WebSocketRedisSubscriberEvent.QueueJobError: {\n // const parsedMessage = JSON.parse(message);\n\n // action and data is separate\n // TODO: Instead allow to pass anything\n parsedMessage.data = parsedMessage.error;\n\n break;\n }\n case WebSocketRedisSubscriberEvent.Custom: {\n // Custom logic is being handled in the app\n\n break;\n }\n default: {\n log('Unknown subscriber message received', {\n Channel: channel,\n Message: message,\n });\n }\n }\n\n if (typeof this.applicationConfig.webSocket?.subscriberEventHandler === 'function') {\n // Execute custom application subscriber event handler\n this.applicationConfig.webSocket.subscriberEventHandler({\n channel,\n message: parsedMessage,\n webSocketServer: this,\n databaseInstance: this.databaseInstance,\n });\n }\n };\n\n private handleServerError = (error: Error): void => {\n Logger.error({ error });\n };\n\n private handleServerClientConnection = (\n ws: WebSocket,\n authenticatedUser?: { userId: number; payload: any } | null,\n ): void => {\n const clientId = generateClientId();\n\n const lastActivity = Date.now();\n\n ws.on('message', (message: RawData) => this.handleClientMessage(ws, message));\n\n ws.on('close', () => {\n this.handleServerClientDisconnection(clientId);\n this.clientManager.removeClient(clientId);\n\n // Clean up event listeners to prevent memory leaks\n ws.removeAllListeners();\n });\n\n try {\n this.clientManager.addClient({\n clientId,\n ws,\n lastActivity,\n user: authenticatedUser,\n });\n\n // Let other workers know that the client has connected\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientConnected,\n JSON.stringify({\n clientId,\n lastActivity,\n workerId: this.workerId,\n user: authenticatedUser,\n }),\n );\n\n // Send authentication success message if user is authenticated\n if (authenticatedUser) {\n this.sendClientMessage(ws, {\n type: 'auth',\n action: 'authenticated',\n data: {\n userId: authenticatedUser.userId,\n message: 'Authentication successful',\n },\n });\n }\n } catch (error) {\n logger.error({ error });\n }\n };\n\n public leaveRoom({ ws, roomName }: { ws: WebSocket; roomName: string }): void {\n const clientId = this.clientManager.getClientId({ ws });\n\n if (!clientId) {\n log('Client ID not found when removing client from room');\n\n return;\n }\n\n // Check if client is in room\n const clientInRoom = this.roomManager.isClientInRoom({\n clientId,\n roomName,\n });\n\n if (!clientInRoom) {\n log('Client not in room when removing client from room', {\n 'Client ID': clientId || '-',\n 'Room Name': roomName,\n });\n\n return;\n }\n\n this.roomManager.removeClientFromRoom({\n roomName,\n clientId,\n });\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientLeftRoom,\n JSON.stringify({\n clientId,\n room: roomName,\n workerId: this.workerId,\n }),\n );\n\n // Optionally send a message to the client\n this.sendClientMessage(ws, {\n type: 'user',\n action: 'leftRoom',\n data: {\n roomName,\n },\n });\n }\n\n private onClientConnect({\n clientId,\n lastActivity,\n user,\n }: {\n clientId: string;\n lastActivity: number;\n user?: { userId: number; payload: any } | null;\n }): void {\n this.clientManager.addClient({\n clientId,\n ws: null,\n lastActivity,\n user,\n });\n }\n\n private onClientDisconnect({ clientId }: { clientId: string }): void {\n // Set client as disconnected\n this.clientManager.removeClient(clientId);\n\n // Remove client from rooms\n this.roomManager.removeClientFromAllRooms({ clientId });\n }\n\n private handleServerClientDisconnection = (clientId: string): void => {\n const client = this.clientManager.getClient({\n clientId,\n });\n\n if (!client) {\n log('Client not found when handling server client disconnection', {\n 'Client ID': clientId || '-',\n });\n\n return;\n }\n\n this.onClientDisconnect({ clientId });\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientDisconnected,\n JSON.stringify({\n clientId,\n workerId: this.workerId,\n }),\n );\n\n // log('Client disconnected', { ID: clientId });\n };\n\n private handleClientMessage = async (ws: WebSocket, message: RawData): Promise<void> => {\n try {\n const clientId = this.clientManager.getClientId({\n ws,\n });\n\n if (!clientId) {\n log('Client ID not found when handling server message');\n\n return;\n }\n\n // Handle server message\n const serverMessageResponse = await this.handleServerMessage(ws, message, clientId);\n\n if (serverMessageResponse) {\n this.sendClientMessage(ws, {\n type: serverMessageResponse.type,\n action: serverMessageResponse.action,\n response: serverMessageResponse?.response,\n });\n\n if (serverMessageResponse?.response?.error) {\n // throw new Error(serverMessageResponse?.response?.error);\n\n Logger.error({ error: serverMessageResponse.response.error });\n }\n }\n } catch (error) {\n Logger.error({ error });\n\n log('Error handling client message', {\n Error: error,\n });\n }\n };\n\n protected handleMessageError(clientId: string, error: string): void {\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.MessageError,\n JSON.stringify({\n runSameWorker: true,\n clientId,\n error,\n }),\n );\n }\n\n private checkInactiveClients(): void {\n // const now = Date.now();\n\n if (this.options.disconnectInactiveClients?.enabled && this.options.disconnectInactiveClients.log) {\n log('Checking inactive clients...');\n }\n }\n\n public broadcastToAllClients({\n data,\n excludeClientId,\n }: {\n data: { [key: string]: any };\n excludeClientId?: string;\n }): void {\n if (!this.server) {\n log('Server not started when broadcasting to all clients');\n\n return;\n }\n\n this.server.clients.forEach(client => {\n let excludeClient = false;\n\n if (excludeClientId) {\n const clientId = this.clientManager.getClientId({\n ws: client,\n });\n\n excludeClient = clientId === excludeClientId;\n }\n\n if (client.readyState === WebSocket.OPEN && !excludeClient) {\n client.send(JSON.stringify(data));\n }\n });\n }\n\n public sendMessageError({ webSocketClientId, error }: { webSocketClientId: string; error: string }): void {\n const client = this.clientManager.getClient({\n clientId: webSocketClientId,\n });\n\n if (!client) {\n log('Client not found when sending message error', {\n 'Client ID': webSocketClientId || '-',\n Error: error,\n });\n\n return;\n } else if (!client.ws) {\n log('Client WebSocket not found when sending message error', {\n 'Client ID': webSocketClientId || '-',\n Error: error,\n });\n\n return;\n }\n\n this.sendClientMessage(client.ws, {\n type: 'error',\n action: 'message',\n data: {\n error,\n },\n });\n }\n\n // private getClientId({\n // client,\n // }: {\n // client: WebSocket;\n // }): string | undefined {\n // return [...this.connectedClients.entries()].find(\n // ([_, value]) => value.ws === client,\n // )?.[0];\n // }\n\n private onJoinRoom({ clientId, roomName, userData }: { clientId: string; roomName: string; userData: any }): void {\n // TODO: If config clientCanJoinMultipleRooms !== true, then it should remove the user from existing room first\n const client = this.clientManager.getClient({\n clientId,\n });\n\n if (!client) {\n log('Client not found when joining room', {\n 'Client ID': clientId || '-',\n 'Room Name': roomName,\n });\n\n return;\n }\n\n const clientCanJoinMultipleRooms: any = false;\n\n if (clientCanJoinMultipleRooms !== true) {\n if (client.roomName) {\n // Remove client from current room\n this.roomManager.removeClientFromRoom({\n roomName: client.roomName,\n clientId,\n });\n }\n }\n\n // Update client with user in client manager\n this.clientManager.updateClient({\n clientId,\n key: 'user',\n data: userData,\n });\n\n this.roomManager.addClientToRoom({\n clientId,\n user: userData,\n roomName,\n });\n }\n\n public async joinRoom({\n ws,\n userId,\n userType,\n username,\n roomName,\n }: {\n ws: WebSocket;\n userId?: number;\n userType?: string;\n username?: string;\n roomName: string;\n }) {\n const clientId = this.clientManager.getClientId({ ws });\n\n if (!clientId) {\n // throw new Error('Client ID not found when joining room');\n\n logger.warn({\n message: 'Client ID not found when joining room',\n meta: {\n // 'WebSocket ID': ws?.id || '-',\n 'Room Name': roomName,\n },\n });\n\n return;\n }\n\n // Check if client is already in room\n const isClientInRoom = this.roomManager.isClientInRoom({\n clientId,\n roomName,\n });\n\n if (isClientInRoom) {\n // throw new Error('Client already in room when joining');\n\n logger.warn({\n message: 'Client already in room when joining',\n meta: {\n // 'WebSocket ID': ws?. || '-',\n 'Room Name': roomName,\n 'Client ID': clientId,\n },\n });\n\n return;\n }\n\n let userData: any = {};\n\n // // Get WebSocket client ID\n // const webSocketId = this.clientManager.getClientId({ ws });\n\n if (userId) {\n // Get user email from database\n const dbEntityManager = this.databaseInstance.getEntityManager();\n\n const getUserQuery = 'SELECT email FROM users WHERE id = ?';\n const getUserParams = [userId];\n\n const getUserResult = await dbEntityManager.execute(getUserQuery, getUserParams);\n\n if (!getUserResult || getUserResult.length === 0) {\n throw new Error('User not found in database');\n }\n\n const user = getUserResult[0];\n\n userData = {\n id: userId,\n ...user,\n };\n }\n\n // userData.uniqueId = webSocketId;\n\n if (username) {\n userData.username = username;\n }\n\n userData.userType = userType;\n\n // if user with same email is already connected, disconnect the previous connection\n // const existingClient =\n // this.clientManager.getClientByKey({\n // key: 'user.email',\n // value: user.email,\n // });\n\n // if (existingClient) {\n // if (existingClient.ws) {\n // this.clientManager.disconnectClient({\n // clientId: existingClient.clientId,\n // });\n // } else {\n // // Publish to Redis that we should disconnect this client\n // this.redisInstance.publisherClient.publish(\n // WebSocketRedisSubscriberEvent.DisconnectClient,\n // JSON.stringify({\n // clientId,\n // workerId: this.workerId,\n // }),\n // );\n // }\n // }\n\n this.onJoinRoom({\n clientId,\n roomName,\n userData,\n });\n\n // Let other workers know that the client has joined the room\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.ClientJoinedRoom,\n JSON.stringify({\n clientId,\n user: userData,\n roomName,\n workerId: this.workerId,\n }),\n );\n\n return true;\n }\n\n public sendClientMessage = (ws: WebSocket, data: unknown, binary: boolean = false): void => {\n const webSocketMessage = JSON.stringify(data);\n\n ws.send(webSocketMessage, { binary });\n };\n\n public sendMessage = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.SendMessage,\n JSON.stringify(formattedData),\n );\n };\n\n public sendMessageToAll = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n this.redisInstance.publisherClient.publish(\n WebSocketRedisSubscriberEvent.SendMessageToAll,\n JSON.stringify(formattedData),\n );\n };\n\n public sendCustomMessage = ({ data }: { data: unknown }): void => {\n const formattedData = {\n ...(data as object),\n workerId: this.workerId,\n };\n\n console.log('SEND CUSTOM MESSAGE:', formattedData);\n\n this.redisInstance.publisherClient.publish(WebSocketRedisSubscriberEvent.Custom, JSON.stringify(formattedData));\n };\n\n public getClients({ userType }: { userType?: string }): any[] {\n return this.clientManager.getClients({ userType });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scpxl/nodejs-framework",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "PXL Node.js Framework",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.0.0"
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"import": "./dist/database/index.js",
|
|
29
29
|
"types": "./dist/database/index.d.ts"
|
|
30
30
|
},
|
|
31
|
+
"./error": {
|
|
32
|
+
"import": "./dist/error/index.js",
|
|
33
|
+
"types": "./dist/error/index.d.ts"
|
|
34
|
+
},
|
|
31
35
|
"./webserver": {
|
|
32
36
|
"import": "./dist/webserver/index.js",
|
|
33
37
|
"types": "./dist/webserver/index.d.ts"
|
|
@@ -44,10 +48,34 @@
|
|
|
44
48
|
"import": "./dist/redis/index.js",
|
|
45
49
|
"types": "./dist/redis/index.d.ts"
|
|
46
50
|
},
|
|
51
|
+
"./request-context": {
|
|
52
|
+
"import": "./dist/request-context/index.js",
|
|
53
|
+
"types": "./dist/request-context/index.d.ts"
|
|
54
|
+
},
|
|
47
55
|
"./cache": {
|
|
48
56
|
"import": "./dist/cache/index.js",
|
|
49
57
|
"types": "./dist/cache/index.d.ts"
|
|
50
58
|
},
|
|
59
|
+
"./performance": {
|
|
60
|
+
"import": "./dist/performance/index.js",
|
|
61
|
+
"types": "./dist/performance/index.d.ts"
|
|
62
|
+
},
|
|
63
|
+
"./command": {
|
|
64
|
+
"import": "./dist/command/index.js",
|
|
65
|
+
"types": "./dist/command/index.d.ts"
|
|
66
|
+
},
|
|
67
|
+
"./auth": {
|
|
68
|
+
"import": "./dist/auth/index.js",
|
|
69
|
+
"types": "./dist/auth/index.d.ts"
|
|
70
|
+
},
|
|
71
|
+
"./api-requester": {
|
|
72
|
+
"import": "./dist/api-requester/index.js",
|
|
73
|
+
"types": "./dist/api-requester/index.d.ts"
|
|
74
|
+
},
|
|
75
|
+
"./lifecycle": {
|
|
76
|
+
"import": "./dist/lifecycle/index.js",
|
|
77
|
+
"types": "./dist/lifecycle/index.d.ts"
|
|
78
|
+
},
|
|
51
79
|
"./util": {
|
|
52
80
|
"import": "./dist/util/index.js",
|
|
53
81
|
"types": "./dist/util/index.d.ts"
|
|
@@ -90,7 +118,16 @@
|
|
|
90
118
|
"check-all": "npm run lint && npm run prettier && npm run typecheck",
|
|
91
119
|
"yalc:publish": "yalc publish",
|
|
92
120
|
"yalc:push": "yalc push",
|
|
93
|
-
"dev:yalc": "npm run build && npm run yalc:push"
|
|
121
|
+
"dev:yalc": "npm run build && npm run yalc:push",
|
|
122
|
+
"example:install": "npm install --prefix examples/hello-world/backend && npm install --prefix examples/hello-world/frontend && npm install --prefix examples/commands",
|
|
123
|
+
"example:hello-world": "concurrently -n backend,frontend -c blue,magenta \"npm run example:hello-world:backend\" \"npm run example:hello-world:frontend\"",
|
|
124
|
+
"example:hello-world:backend": "npm run dev --prefix examples/hello-world/backend",
|
|
125
|
+
"example:hello-world:frontend": "npm run dev --prefix examples/hello-world/frontend",
|
|
126
|
+
"example:commands:install": "npm install --prefix examples/commands",
|
|
127
|
+
"example:commands": "npm run dev --prefix examples/commands --",
|
|
128
|
+
"example:commands:hello": "npm run dev --prefix examples/commands -- hello",
|
|
129
|
+
"example:commands:seed": "npm run dev --prefix examples/commands -- database-seed",
|
|
130
|
+
"example:commands:queue": "npm run dev --prefix examples/commands -- queue-process"
|
|
94
131
|
},
|
|
95
132
|
"keywords": [],
|
|
96
133
|
"author": "PXL <devops@pxlagency.com>",
|
|
@@ -98,6 +135,7 @@
|
|
|
98
135
|
"devDependencies": {
|
|
99
136
|
"@swc/core": "^1.4.1",
|
|
100
137
|
"@types/fluent-ffmpeg": "^2.1.26",
|
|
138
|
+
"@types/lodash.defaultsdeep": "^4.6.9",
|
|
101
139
|
"@types/node": "^24.0.13",
|
|
102
140
|
"@types/uuid": "^10.0.0",
|
|
103
141
|
"@types/ws": "^8.5.10",
|
|
@@ -106,7 +144,8 @@
|
|
|
106
144
|
"@typescript-eslint/parser": "^8.1.0",
|
|
107
145
|
"@vitest/coverage-v8": "^3.2.4",
|
|
108
146
|
"@vitest/ui": "^3.2.4",
|
|
109
|
-
"
|
|
147
|
+
"concurrently": "^9.1.2",
|
|
148
|
+
"del-cli": "^7.0.0",
|
|
110
149
|
"esbuild": "^0.25.5",
|
|
111
150
|
"eslint": "^9.9.0",
|
|
112
151
|
"eslint-config-prettier": "^10.1.5",
|
|
@@ -117,7 +156,7 @@
|
|
|
117
156
|
"husky": "^9.1.7",
|
|
118
157
|
"lint-staged": "^16.1.2",
|
|
119
158
|
"prettier": "^3.1.1",
|
|
120
|
-
"redis-memory-server": "^0.
|
|
159
|
+
"redis-memory-server": "^0.13.0",
|
|
121
160
|
"ts-node": "^10.9.2",
|
|
122
161
|
"tsc-alias": "^1.8.16",
|
|
123
162
|
"tsconfig-paths": "^4.2.0",
|
|
@@ -128,7 +167,9 @@
|
|
|
128
167
|
"@aws-sdk/client-s3": "^3.496.0",
|
|
129
168
|
"@aws-sdk/s3-request-presigner": "^3.675.0",
|
|
130
169
|
"@fastify/cors": "^11.0.0",
|
|
170
|
+
"@fastify/helmet": "^12.0.0",
|
|
131
171
|
"@fastify/multipart": "^9.0.0",
|
|
172
|
+
"@fastify/rate-limit": "^10.0.0",
|
|
132
173
|
"@mikro-orm/cli": "^6.0.5",
|
|
133
174
|
"@mikro-orm/core": "^6.0.5",
|
|
134
175
|
"@mikro-orm/migrations": "^6.0.5",
|
|
@@ -136,23 +177,23 @@
|
|
|
136
177
|
"@mikro-orm/seeder": "^6.0.5",
|
|
137
178
|
"@sentry/node": "^9.37.0",
|
|
138
179
|
"@sentry/profiling-node": "^9.37.0",
|
|
139
|
-
"axios": "^1.6.2",
|
|
140
180
|
"bullmq": "^5.1.3",
|
|
141
181
|
"dotenv": "^17.2.0",
|
|
142
182
|
"fastify": "^5.0.0",
|
|
143
183
|
"fluent-ffmpeg": "^2.1.3",
|
|
144
184
|
"http-status-codes": "^2.3.0",
|
|
145
185
|
"ioredis": "^5.3.2",
|
|
146
|
-
"joi": "^
|
|
186
|
+
"joi": "^18.0.1",
|
|
147
187
|
"jose": "^6.0.10",
|
|
148
|
-
"
|
|
149
|
-
"
|
|
188
|
+
"lodash.defaultsdeep": "^4.6.1",
|
|
189
|
+
"lru-cache": "^11.2.2",
|
|
150
190
|
"typescript": "^5.8.3",
|
|
151
|
-
"uuid": "^
|
|
191
|
+
"uuid": "^13.0.0",
|
|
152
192
|
"winston": "^3.11.0",
|
|
153
193
|
"ws": "^8.15.1",
|
|
154
194
|
"yalc": "^1.0.0-pre.53",
|
|
155
|
-
"yargs": "^18.0.0"
|
|
195
|
+
"yargs": "^18.0.0",
|
|
196
|
+
"zod": "^4.1.5"
|
|
156
197
|
},
|
|
157
198
|
"lint-staged": {
|
|
158
199
|
"*.{ts,js}": [
|