Overview
Add real-time capabilities to your app using @fastify/websocket. Perfect for chat, live updates, and collaborative features.
Features
- WebSocket integration with Fastify
- Client connection tracking
- Message type handling
- Broadcast functionality
- Connection metadata
Installation
npx hanma add fastify-socket-server --framework fastify
Dependencies
fastify, @fastify/websocket
Code
import Fastify, { FastifyInstance } from "fastify";
import websocket, { WebSocket } from "@fastify/websocket";
interface Client {
id: string;
socket: WebSocket;
metadata?: Record<string, unknown>;
}
const clients = new Map<string, Client>();
function generateClientId(): string {
return `client_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
}
export async function createSocketServer(): Promise<FastifyInstance> {
const app = Fastify({
logger: {
level: process.env.LOG_LEVEL ?? "info",
},
});
await app.register(websocket, {
options: {
maxPayload: 1048576, // 1MB
clientTracking: true,
},
});
// WebSocket route
app.get("/ws", { websocket: true }, (socket, request) => {
const clientId = generateClientId();
const client: Client = {
id: clientId,
socket,
metadata: {
ip: request.ip,
userAgent: request.headers["user-agent"],
connectedAt: new Date().toISOString(),
},
};
clients.set(clientId, client);
app.log.info({ clientId }, "Client connected");
// Send welcome message
socket.send(JSON.stringify({
type: "connected",
clientId,
timestamp: new Date().toISOString(),
}));
socket.on("message", (rawMessage) => {
try {
const message = JSON.parse(rawMessage.toString());
app.log.debug({ clientId, message }, "Message received");
// Handle different message types
switch (message.type) {
case "ping":
socket.send(JSON.stringify({ type: "pong", timestamp: Date.now() }));
break;
case "broadcast":
broadcast(message.data, clientId);
break;
default:
socket.send(JSON.stringify({
type: "echo",
data: message,
timestamp: new Date().toISOString(),
}));
}
} catch (err) {
app.log.error({ clientId, error: err }, "Error processing message");
socket.send(JSON.stringify({
type: "error",
message: "Invalid message format"
}));
}
});
socket.on("close", () => {
clients.delete(clientId);
app.log.info({ clientId }, "Client disconnected");
});
socket.on("error", (err) => {
app.log.error({ clientId, error: err }, "WebSocket error");
clients.delete(clientId);
});
});
// Health check with connection count
app.get("/health", async () => ({
status: "healthy",
connections: clients.size,
timestamp: new Date().toISOString(),
}));
return app;
}
// Broadcast to all clients except sender
function broadcast(data: unknown, senderId?: string): void {
const message = JSON.stringify({ type: "broadcast", data, from: senderId });
clients.forEach((client) => {
if (client.id !== senderId && client.socket.readyState === 1) {
client.socket.send(message);
}
});
}
// Get all connected clients
export function getClients(): Client[] {
return Array.from(clients.values());
}
// Send to specific client
export function sendToClient(clientId: string, data: unknown): boolean {
const client = clients.get(clientId);
if (client && client.socket.readyState === 1) {
client.socket.send(JSON.stringify(data));
return true;
}
return false;
}
// Usage:
// const app = await createSocketServer();
// await app.listen({ port: 3000 });
Usage
import { createSocketServer } from './socket-server';
const app = await createSocketServer();
await app.listen({ port: 3000 });
Dependencies
fastify@fastify/websocket
Frequently Asked Questions
How do I install WebSocket Server?
Run the following command:
npx hanma add fastify-socket-server --framework fastifyWhat dependencies are required?
This snippet requires: fastify, @fastify/websocket. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/socket-server.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.