websocket-server.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import { WebSocketServer, WebSocket } from 'ws';
  2. import { Server } from 'http';
  3. import { ImportProgress } from './types';
  4. export class ImportProgressServer {
  5. private wss: WebSocketServer | null = null;
  6. private clients: Set<WebSocket> = new Set();
  7. constructor() {
  8. // Initialize WebSocket server
  9. this.setupWebSocketServer();
  10. }
  11. private setupWebSocketServer() {
  12. // This will be initialized when the HTTP server is available
  13. // For now, we'll create a standalone WebSocket server
  14. this.wss = new WebSocketServer({ port: 8080 });
  15. this.wss.on('connection', (ws: WebSocket) => {
  16. console.log('New WebSocket connection established');
  17. this.clients.add(ws);
  18. ws.on('close', () => {
  19. console.log('WebSocket connection closed');
  20. this.clients.delete(ws);
  21. });
  22. ws.on('error', (error) => {
  23. console.error('WebSocket error:', error);
  24. this.clients.delete(ws);
  25. });
  26. });
  27. console.log('WebSocket server started on port 8080');
  28. }
  29. // Alternative method to attach to existing HTTP server
  30. attachToServer(server: Server) {
  31. if (this.wss) {
  32. this.wss.close();
  33. }
  34. this.wss = new WebSocketServer({
  35. server,
  36. path: '/api/imports/progress'
  37. });
  38. this.wss.on('connection', (ws: WebSocket, request) => {
  39. console.log('New WebSocket connection on import progress endpoint');
  40. this.clients.add(ws);
  41. // Handle specific import ID subscriptions
  42. const url = new URL(request.url || '', `http://${request.headers.host}`);
  43. const importId = url.searchParams.get('importId');
  44. if (importId) {
  45. ws.send(JSON.stringify({
  46. type: 'connected',
  47. importId: parseInt(importId),
  48. message: 'Connected to import progress updates'
  49. }));
  50. }
  51. ws.on('close', () => {
  52. console.log('WebSocket connection closed');
  53. this.clients.delete(ws);
  54. });
  55. ws.on('error', (error) => {
  56. console.error('WebSocket error:', error);
  57. this.clients.delete(ws);
  58. });
  59. });
  60. }
  61. broadcastProgress(importId: number, progress: ImportProgress) {
  62. const message = JSON.stringify({
  63. type: 'progress',
  64. importId,
  65. progress
  66. });
  67. this.clients.forEach(client => {
  68. if (client.readyState === WebSocket.OPEN) {
  69. client.send(message);
  70. }
  71. });
  72. }
  73. broadcastError(importId: number, error: string) {
  74. const message = JSON.stringify({
  75. type: 'error',
  76. importId,
  77. error
  78. });
  79. this.clients.forEach(client => {
  80. if (client.readyState === WebSocket.OPEN) {
  81. client.send(message);
  82. }
  83. });
  84. }
  85. broadcastComplete(importId: number, result: any) {
  86. const message = JSON.stringify({
  87. type: 'complete',
  88. importId,
  89. result
  90. });
  91. this.clients.forEach(client => {
  92. if (client.readyState === WebSocket.OPEN) {
  93. client.send(message);
  94. }
  95. });
  96. }
  97. close() {
  98. if (this.wss) {
  99. this.wss.close();
  100. this.clients.clear();
  101. }
  102. }
  103. }
  104. // Export a singleton instance
  105. export const progressServer = new ImportProgressServer();