WebSocket Adapters

MoroJS v1.4.0 introduces pluggable WebSocket adapters. Choose Socket.IO for features, native WebSockets for performance, or disable WebSockets entirely for HTTP-only apps.

WebSocket Adapter Configuration

Choose Your WebSocket Adapter

typescript

1import { createApp, SocketIOAdapter, WSAdapter } from '@morojs/moro';
2
3// Option 1: Auto-detection (recommended)
4const app = createApp(); // Uses Socket.IO if available, then ws
5
6// Option 2: Explicit Socket.IO adapter
7const app = createApp({
8  websocket: {
9    adapter: new SocketIOAdapter(),
10    options: {
11      cors: { origin: '*' },
12      path: '/socket.io/',
13      pingTimeout: 60000
14    }
15  }
16});
17
18// Option 3: Native WebSocket adapter (lightweight)
19const app = createApp({
20  websocket: {
21    adapter: new WSAdapter(),
22    options: {
23      path: '/ws',
24      maxPayloadLength: 100 * 1024 * 1024 // 100MB
25    }
26  }
27});
28
29// Option 4: Disable WebSockets (HTTP-only)
30const app = createApp({ websocket: false });

Universal WebSocket Usage

typescript

1// Works with any adapter - same API!
2app.websocket('/chat', {
3  'join-room': (socket, data) => {
4    socket.join(data.room);
5    socket.to(data.room).emit('user-joined', {
6      username: data.username,
7      room: data.room,
8      timestamp: new Date()
9    });
10    return { success: true, room: data.room };
11  },
12
13  'send-message': (socket, data) => {
14    socket.to(data.room).emit('new-message', {
15      id: Date.now(),
16      message: data.message,
17      sender: data.username,
18      room: data.room,
19      timestamp: new Date()
20    });
21    return { success: true };
22  },
23
24  'disconnect': (socket) => {
25    // Cleanup logic for any adapter
26    console.log(`User ${socket.id} disconnected`);
27  }
28});

Advanced WebSocket Features

WebSocket Event Handling

typescript

1// Based on actual feature-showcase implementation
2app.websocket('/chat', {
3  join: (socket, data) => {
4    socket.join('chat-room');
5    socket.to('chat-room').emit('user-joined', { 
6      message: `${data.username} joined the chat` 
7    });
8    return { success: true, message: 'Joined chat room' };
9  },
10  
11  message: (socket, data) => {
12    socket.to('chat-room').emit('message', {
13      username: data.username,
14      message: data.message,
15      timestamp: new Date().toISOString()
16    });
17    return { success: true };
18  }
19});
20
21// Simple WebSocket endpoint without rooms
22app.websocket('/notifications', {
23  connect: (socket) => {
24    console.log('Notification client connected');
25    socket.emit('welcome', { 
26      message: 'Connected to notifications' 
27    });
28  },
29  
30  disconnect: (socket) => {
31    console.log('Notification client disconnected');
32  },
33  
34  subscribe: (socket, data) => {
35    const { channel } = data;
36    socket.join(channel);
37    return { success: true, channel };
38  }
39});

Authentication & Middleware

typescript

1// WebSocket with authentication
2app.ws('/secure-chat', {
3  middleware: [
4    // Auth middleware for WebSocket
5    async ({ request }) => {
6      const token = request.headers.get('authorization');
7      if (!token) {
8        throw new Error('Authentication required');
9      }
10      
11      const user = await verifyToken(token);
12      return { user };
13    }
14  ],
15  
16  onConnect: (socket, request, context) => {
17    // context.user is available from middleware
18    socket.user = context.user;
19    
20    console.log(`User ${context.user.name} connected`);
21    
22    socket.send({
23      type: 'authenticated',
24      user: context.user
25    });
26  },
27  
28  onMessage: (socket, message) => {
29    // Handle authenticated user messages
30    if (message.type === 'private-message') {
31      const targetSocket = wsManager.findByUserId(message.targetUserId);
32      if (targetSocket) {
33        targetSocket.send({
34          type: 'private-message',
35          from: socket.user.name,
36          message: message.text
37        });
38      }
39    }
40  }
41});

WebSocket Adapter Comparison

AdapterBundle SizePerformanceFeaturesUse Case
Socket.IO~244KBGoodRich (rooms, namespaces)Feature-rich apps
Native WS~8KBExcellentLightweightPerformance-focused
None0KBN/AHTTP onlyREST APIs

Installation Guide

Socket.IO Projects

npm install socket.io
# Auto-detected

Native WebSocket

npm install ws @types/ws
# Lightweight option

HTTP-Only

No additional deps
# Just disable WS

Next Steps