forked from noxious/server
Moved more socket logic into socket manager for easier DX
This commit is contained in:
parent
a5c941cbb0
commit
ba12674e7c
@ -4,6 +4,7 @@ import { CommandRegistry } from '#application/console/commandRegistry'
|
||||
import { ConsolePrompt } from '#application/console/consolePrompt'
|
||||
import { LogReader } from '#application/console/logReader'
|
||||
import Logger, { LoggerType } from '#application/logger'
|
||||
import SocketManager from '#managers/socketManager'
|
||||
|
||||
export class ConsoleManager {
|
||||
private readonly logger = Logger.type(LoggerType.COMMAND)
|
||||
@ -19,8 +20,8 @@ export class ConsoleManager {
|
||||
this.logReader = new LogReader(process.cwd())
|
||||
}
|
||||
|
||||
public async boot(io: Server): Promise<void> {
|
||||
this.io = io
|
||||
public async boot(): Promise<void> {
|
||||
this.io = SocketManager.getIO()
|
||||
|
||||
await this.registry.loadCommands()
|
||||
this.logReader.start()
|
||||
|
@ -8,6 +8,7 @@ import config from '#application/config'
|
||||
import Logger, { LoggerType } from '#application/logger'
|
||||
import { getAppPath } from '#application/storage'
|
||||
import { TSocket } from '#application/types'
|
||||
import SocketManager from '#managers/socketManager'
|
||||
|
||||
class QueueManager {
|
||||
private connection!: IORedis
|
||||
@ -16,8 +17,8 @@ class QueueManager {
|
||||
private io!: SocketServer
|
||||
private logger = Logger.type(LoggerType.QUEUE)
|
||||
|
||||
public async boot(io: SocketServer) {
|
||||
this.io = io
|
||||
public async boot() {
|
||||
this.io = SocketManager.getIO()
|
||||
|
||||
this.connection = new IORedis(config.REDIS_URL, {
|
||||
maxRetriesPerRequest: null
|
||||
|
@ -1,27 +1,53 @@
|
||||
import { Server as SocketServer } from 'socket.io'
|
||||
import fs from 'fs'
|
||||
import { pathToFileURL } from 'url'
|
||||
|
||||
import { Server as SocketServer } from 'socket.io'
|
||||
import { Server as HTTPServer } from 'http'
|
||||
import { Application } from 'express'
|
||||
|
||||
import Logger, { LoggerType } from '#application/logger'
|
||||
import { getAppPath } from '#application/storage'
|
||||
import { TSocket } from '#application/types'
|
||||
import config from '#application/config'
|
||||
import { Authentication } from '#middleware/authentication'
|
||||
|
||||
class SocketManager {
|
||||
private io: any
|
||||
private logger = Logger.type(LoggerType.APP)
|
||||
private io: SocketServer | null = null
|
||||
private readonly logger = Logger.type(LoggerType.APP)
|
||||
|
||||
public async boot(io: SocketServer) {
|
||||
this.io = io
|
||||
io.on('connection', this.handleConnection.bind(this))
|
||||
/**
|
||||
* Initialize Socket.IO server
|
||||
*/
|
||||
public async boot(app: Application, http: HTTPServer): Promise<void> {
|
||||
this.io = new SocketServer(http, {
|
||||
cors: {
|
||||
origin: config.CLIENT_URL,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization'],
|
||||
credentials: true
|
||||
}
|
||||
})
|
||||
|
||||
// Apply authentication middleware
|
||||
this.io.use(Authentication)
|
||||
|
||||
// Set up connection handler
|
||||
this.io.on('connection', this.handleConnection.bind(this))
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket.IO server instance
|
||||
*/
|
||||
public getIO(): SocketServer {
|
||||
if (!this.io) {
|
||||
throw new Error('Socket.IO has not been initialized')
|
||||
}
|
||||
return this.io
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle socket connection
|
||||
* @param socket
|
||||
* @private
|
||||
*/
|
||||
private async handleConnection(socket: TSocket) {
|
||||
private async handleConnection(socket: TSocket): Promise<void> {
|
||||
try {
|
||||
await this.loadEventHandlers('events', '', socket)
|
||||
} catch (error: any) {
|
||||
@ -29,7 +55,10 @@ class SocketManager {
|
||||
}
|
||||
}
|
||||
|
||||
private async loadEventHandlers(baseDir: string, subDir: string, socket: TSocket) {
|
||||
/**
|
||||
* Load event handlers recursively from the events directory
|
||||
*/
|
||||
private async loadEventHandlers(baseDir: string, subDir: string, socket: TSocket): Promise<void> {
|
||||
try {
|
||||
const fullDir = getAppPath(baseDir, subDir)
|
||||
const files = await fs.promises.readdir(fullDir, { withFileTypes: true })
|
||||
@ -64,6 +93,20 @@ class SocketManager {
|
||||
this.logger.error(`Error reading directory: ${error instanceof Error ? error.message : String(error)}`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit event to all connected clients
|
||||
*/
|
||||
public emit(event: string, ...args: any[]): void {
|
||||
this.getIO().emit(event, ...args)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit event to specific room
|
||||
*/
|
||||
public emitToRoom(room: string, event: string, ...args: any[]): void {
|
||||
this.getIO().to(room).emit(event, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
export default new SocketManager()
|
||||
export default new SocketManager()
|
@ -1,8 +1,6 @@
|
||||
import { createServer as httpServer, Server as HTTPServer } from 'http'
|
||||
|
||||
import cors from 'cors'
|
||||
import express, { Application } from 'express'
|
||||
import { Server as SocketServer } from 'socket.io'
|
||||
import cors from 'cors'
|
||||
|
||||
import config from '#application/config'
|
||||
import Database from '#application/database'
|
||||
@ -15,77 +13,45 @@ import SocketManager from '#managers/socketManager'
|
||||
import UserManager from '#managers/userManager'
|
||||
import WeatherManager from '#managers/weatherManager'
|
||||
import ZoneManager from '#managers/zoneManager'
|
||||
import { Authentication } from '#middleware/authentication'
|
||||
|
||||
export class Server {
|
||||
private readonly app: Application
|
||||
private readonly http: HTTPServer
|
||||
private readonly io: SocketServer
|
||||
private readonly logger = Logger.type(LoggerType.APP)
|
||||
|
||||
/**
|
||||
* Creates an instance of GameServer.
|
||||
*/
|
||||
constructor() {
|
||||
this.app = express()
|
||||
this.app.use(
|
||||
cors({
|
||||
origin: config.CLIENT_URL,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // Add supported methods
|
||||
allowedHeaders: ['Content-Type', 'Authorization'], // Add allowed headers
|
||||
credentials: true
|
||||
})
|
||||
)
|
||||
this.app.use(cors())
|
||||
this.app.use(express.json())
|
||||
this.app.use(express.urlencoded({ extended: true }))
|
||||
this.http = httpServer(this.app)
|
||||
this.io = new SocketServer(this.http)
|
||||
this.io.use(Authentication)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the server
|
||||
*/
|
||||
public async start() {
|
||||
// Connect to database
|
||||
public async start(): Promise<void> {
|
||||
try {
|
||||
// Initialize database
|
||||
await Database.initialize()
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Database connection failed: ${error.message}`)
|
||||
process.exit(1) // Exit if database connection fails
|
||||
}
|
||||
|
||||
// Start the server
|
||||
try {
|
||||
// Start HTTP server
|
||||
this.http.listen(config.PORT, config.HOST)
|
||||
this.logger.info(`Socket.IO running on port ${config.PORT}`)
|
||||
this.logger.info(`Server running on port ${config.PORT}`)
|
||||
|
||||
// Initialize managers
|
||||
await Promise.all([
|
||||
HttpManager.boot(this.app),
|
||||
SocketManager.boot(this.app, this.http),
|
||||
QueueManager.boot(),
|
||||
UserManager.boot(),
|
||||
// DateManager.boot(SocketManager.getIO()),
|
||||
// WeatherManager.boot(SocketManager.getIO()),
|
||||
ZoneManager.boot(),
|
||||
ConsoleManager.boot()
|
||||
])
|
||||
|
||||
} catch (error: any) {
|
||||
this.logger.error(`Socket.IO failed to start: ${error.message}`)
|
||||
this.logger.error(`Server failed to start: ${error.message}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Load HTTP manager
|
||||
await HttpManager.boot(this.app)
|
||||
|
||||
// Load queue manager
|
||||
await QueueManager.boot(this.io)
|
||||
|
||||
// Load user manager
|
||||
await UserManager.boot()
|
||||
|
||||
// Load date manager
|
||||
// await DateManager.boot(this.io)
|
||||
|
||||
// Load weather manager
|
||||
// await WeatherManager.boot(this.io)
|
||||
|
||||
// Load zoneEditor manager
|
||||
await ZoneManager.boot()
|
||||
|
||||
// Load console manager
|
||||
await ConsoleManager.boot(this.io)
|
||||
|
||||
// Load socket manager
|
||||
await SocketManager.boot(this.io)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user