Protocols
WebSocket Adapters
Pluggable WebSocket adapters. Choose Socket.IO for features, native WebSockets for performance, or disable WebSockets entirely for HTTP-only apps.
Overview
Different apps need different WebSocket solutions. With MoroJS, you choose the adapter that fits your needs - same API, different backends. Traditional WebSocket setup locks you into one solution. We give you flexibility with a consistent API.
Without Adapters
- Locked into one WebSocket library
- Different APIs for different libraries
- Hard to switch between solutions
- No flexibility for different use cases
With MoroJS
- Choose the adapter that fits your needs
- Same API across all adapters
- Easy to switch between adapters
- Auto-detection for zero config
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});Flexible
Choose Socket.IO for features or native WS for performance. Same API.
Automatic
Auto-detection finds the best adapter. Zero configuration needed.
Consistent
Same API across all adapters. Switch between them easily.
How It Works
MoroJS uses a pluggable adapter system for WebSockets. You can choose Socket.IO for feature-rich applications, native WebSocket (ws) for performance, or disable WebSockets entirely for HTTP-only apps. The API remains consistent across all adapters.
WebSocket Adapter Configuration
1import { createApp, SocketIOAdapter, WSAdapter } from '@morojs/moro';
2
3// Option 1: Auto-detection (recommended)
4const app = await createApp(); // Uses Socket.IO if available, then ws
5
6// Option 2: Explicit Socket.IO adapter
7const app = await 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 = await 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 = await createApp({ websocket: false });Advanced WebSocket Features
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});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
| Adapter | Bundle Size | Performance | Features | Use Case |
|---|---|---|---|---|
| Socket.IO | ~244KB | Good | Rich (rooms, namespaces) | Feature-rich apps |
| Native WS | ~8KB | Excellent | Lightweight | Performance-focused |
| None | 0KB | N/A | HTTP only | REST APIs |