import { WebSocketGateway, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, } from '@nestjs/websockets'; import { Logger } from '@nestjs/common'; import { Server, Socket } from 'socket.io'; import { WS_EVENTS, JobProgressEvent, JobCompletedEvent, JobFailedEvent, SegmentEvent, VersionEvent, ProjectStatusEvent, } from './ws-events'; /** * SkriptAI WebSocket Gateway * * Socket.IO gateway for real-time notifications. * Clients join project-specific rooms to receive updates. * * TR: Gerçek zamanlı bildirimler için Socket.IO gateway. * İstemciler proje odalarına katılarak güncellemeler alır. */ @WebSocketGateway({ namespace: '/skriptai', cors: { origin: '*', credentials: true, }, }) export class SkriptaiGateway implements OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server: Server; private readonly logger = new Logger(SkriptaiGateway.name); handleConnection(client: Socket) { this.logger.log(`Client connected: ${client.id}`); } handleDisconnect(client: Socket) { this.logger.log(`Client disconnected: ${client.id}`); } /** * Client joins a project room to receive project-specific events */ @SubscribeMessage('join:project') handleJoinProject(client: Socket, projectId: string) { const room = `project:${projectId}`; client.join(room); this.logger.debug(`Client ${client.id} joined room ${room}`); return { status: 'ok', room }; } /** * Client leaves a project room */ @SubscribeMessage('leave:project') handleLeaveProject(client: Socket, projectId: string) { const room = `project:${projectId}`; client.leave(room); this.logger.debug(`Client ${client.id} left room ${room}`); return { status: 'ok' }; } // ========== EMIT METHODS (called by processors/services) ========== /** * Emit job progress to all clients in the project room */ emitJobProgress(event: JobProgressEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(WS_EVENTS.JOB_PROGRESS, event); } /** * Emit job completed */ emitJobCompleted(event: JobCompletedEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(WS_EVENTS.JOB_COMPLETED, event); } /** * Emit job failed */ emitJobFailed(event: JobFailedEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(WS_EVENTS.JOB_FAILED, event); } /** * Emit segment generated/updated */ emitSegmentEvent(eventName: string, event: SegmentEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(eventName, event); } /** * Emit version created/restored */ emitVersionEvent(eventName: string, event: VersionEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(eventName, event); } /** * Emit project status change */ emitProjectStatusChanged(event: ProjectStatusEvent) { const room = `project:${event.projectId}`; this.server.to(room).emit(WS_EVENTS.PROJECT_STATUS_CHANGED, event); } }