npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sockular

v0.2.4

Published

A modular, decorator-based framework for building scalable Socket.IO applications with TypeScript

Readme

Sockular

A modular, decorator-based framework for building scalable Socket.IO applications with TypeScript.

Overview

Sockular transforms the way you build real-time applications by providing a clean, modular architecture that eliminates boilerplate code and promotes best practices. Built on top of Socket.IO, it brings structure and maintainability to WebSocket applications through TypeScript decorators and a powerful middleware system.

Key Features

  • Decorator-Based API: Define message handlers and room logic using intuitive TypeScript decorators
  • Modular Architecture: Organize your real-time logic into reusable services
  • Three-Level Middleware System: Apply middleware at global, service, or method level
  • Auto-Discovery: Automatically discover and register services from your codebase
  • Unified Client API: Fluent and Decorative APIs for seamless frontend integration
  • Declarative Room Management: Manage rooms easily with @JoinRoom, @LeaveRoom, and @EmitToRoom
  • Socket.IO Dependency Injection: Inject the Socket.IO server instance directly into your services
  • Type-Safe: Full TypeScript support with comprehensive type definitions
  • Secure by Default: Global middleware enforcement with explicit opt-out for public endpoints
  • Built-in Rate Limiting: Protect your server from spam with configurable built-in rate limiting
  • CLI Tools: Scaffolding commands for project initialization and component generation (scr / sockular)

Installation

npm install sockular

CLI Usage

Sockular comes with a powerful CLI to speed up your development. You can use either sockular or the shortcut scr.

Initialize a new project

npx sockular init my-app

Generate components

# Generate a service
npx sockular g service chat

# Generate a middleware
npx sockular g middleware auth

Quick Start

1. Create a Service

import { Service, OnMessage, OnConnect, OnDisconnect } from 'sockular';
import { Socket } from 'sockular';

@Service('chat')
export class ChatService {
  @OnConnect()
  async handleConnect(socket: Socket, clientId: string) {
    console.log(`Client ${clientId} connected to chat`);
  }

  @OnMessage('send_message')
  async handleSendMessage(socket: Socket, data: any, clientId: string) {
    // Handle incoming message
    socket.emit('message_received', {
      message: data.message,
      timestamp: Date.now(),
    });
  }

  @OnDisconnect()
  async handleDisconnect(socket: Socket, clientId: string) {
    console.log(`Client ${clientId} disconnected`);
  }
}

2. Initialize the Server

import { SockularServer } from 'sockular';
import { ChatService } from './services/chat.service';

const server = new SockularServer({
  port: 3000,
  enableLogging: true,
});

// Register services
server.register(ChatService);

// Start the server
await server.start();

3. Connect from Client

import io from 'socket.io-client';

const socket = io('http://localhost:3000', {
  auth: { token: 'your-auth-token' },
});

socket.emit('message', {
  service: 'chat',
  type: 'send_message',
  data: { message: 'Hello, world!' },
});

4. Using the Sockular Client (Recommended)

Sockular provides a dedicated client for a better developer experience:

import { Client } from 'sockular';

@Client.SetUrl('http://localhost:3000')
class ChatClient {
  @Client.OnConnect()
  onConnect() {
    console.log('Connected!');
  }

  @Client.OnMessage('chat', 'message_received')
  onMessage(data: any) {
    console.log('Received:', data.message);
  }
}

const chat = Client.create(ChatClient);

See the Client API Documentation for more details.

Middleware System

Sockular provides a powerful three-level middleware system for authentication, validation, rate limiting, and more.

Defining Middleware

import { Middleware } from 'sockular';

export const authMiddleware: Middleware = async (socket, data, clientId, next) => {
  const token = socket.handshake.auth?.token;

  if (!token) {
    throw new Error('Authentication required');
  }

  const user = await validateToken(token);
  socket.data.user = user;

  await next();
};

Applying Middleware

// Global middleware (applied to all messages)
server.registerMiddleware('auth', authMiddleware);
server.use('auth');

// Service-level middleware
@Service('chat', {
  middleware: ['validation']
})
export class ChatService { }

// Method-level middleware
@OnMessage('admin_action')
@UseMiddleware('adminOnly')
async handleAdminAction(socket: Socket, data: any, clientId: string) { }

// Skip global middleware for public endpoints
@OnMessage('login')
@SkipMiddleware('auth')
async handleLogin(socket: Socket, data: any, clientId: string) { }

Decorators

@Service(name, options?)

Marks a class as a Sockular service.

@Service('chat', {
  middleware: ['validation'],
  rateLimit: { maxRequests: 100, windowMs: 60000 },
})
export class ChatService {}

@OnMessage(messageType)

Defines a handler for a specific message type.

@OnMessage('send_message')
async handleSendMessage(socket: Socket, data: any, clientId: string) { }

@OnConnect()

Called when a client connects to the service.

@OnConnect()
async handleConnect(socket: Socket, clientId: string) { }

@OnDisconnect()

Called when a client disconnects.

@OnDisconnect()
async handleDisconnect(socket: Socket, clientId: string) { }

@UseMiddleware(...names)

Applies additional middleware to a specific method.

@UseMiddleware('adminOnly', 'validation')
async handleAdminAction(socket: Socket, data: any, clientId: string) { }

@SkipMiddleware(...names)

Excludes global middleware from a specific method.

@SkipMiddleware('auth')
async handlePublicEndpoint(socket: Socket, data: any, clientId: string) { }

### @JoinRoom(room)

Automatically adds the client's socket to a specific room. The `room` parameter can be a string or a function taking `data` as an argument.

```typescript
@OnMessage('join_chat')
@JoinRoom((data) => `room_${data.id}`)
async handleJoin() {}

@LeaveRoom(room)

Automatically removes the client's socket from a specific room.

@OnMessage('leave_chat')
@LeaveRoom('global_chat')
async handleLeave() {}

@EmitToRoom(room, event)

Broadcasts the returned value of the handler to everyone in the specified room.

@OnMessage('send_message')
@EmitToRoom((data) => `room_${data.id}`, 'new_message')
async handleSend(socket, data) {
  return { text: data.message };
}

@SocketIO()

Injects the native Socket.IO Server instance into a class property.

@SocketIO()
private io: Server;

## Auto-Discovery

Automatically discover and register services from a directory:

```typescript
await server.discoverServices('./services');

Configuration

const server = new SockularServer({
  port: 3000,
  host: 'localhost',
  enableLogging: true,
  enableHeartbeat: true,
  sessionTimeout: 600000,
  maxConnections: 1000,
  rateLimit: {
    enabled: true,
    windowMs: 60000,
    maxRequests: 100,
    global: true, // Apply to all messages automatically
    message: 'Too many requests, please try again later.',
  },
});

Built-in Rate Limiting

Sockular includes a built-in rate limiting middleware that can be enabled globally or registered for specific use.

const server = new SockularServer({
  port: 3000,
  rateLimit: {
    enabled: true,
    windowMs: 5000, // 5 seconds
    maxRequests: 5,
    global: true,
  },
});

If global is set to false, you can still apply it to specific services or methods using the name 'rateLimit':

@Service('chat')
@UseMiddleware('rateLimit')
export class ChatService {}

Architecture Benefits

Before Sockular

io.on('connection', (socket) => {
  socket.on('send_message', async (data) => {
    /* ... */
  });
  socket.on('typing', async (data) => {
    /* ... */
  });
  socket.on('join_room', async (data) => {
    /* ... */
  });
  socket.on('leave_room', async (data) => {
    /* ... */
  });
  socket.on('delete_message', async (data) => {
    /* ... */
  });
  // Hundreds of handlers in one file...
});

With Sockular

@Service('chat')
export class ChatService {
  @OnMessage('send_message')
  async handleSendMessage(socket, data, clientId) {}

  @OnMessage('typing')
  async handleTyping(socket, data, clientId) {}

  @OnMessage('join_room')
  async handleJoinRoom(socket, data, clientId) {}
}

Clean, modular, and maintainable.

Examples

See the examples/ directory for complete working examples:

  • basic/ - Simple chat application
  • with-auth/ - Authentication and authorization
  • with-redis/ - Horizontal scaling with Redis adapter

Requirements

  • Node.js >= 16
  • TypeScript >= 4.5
  • Socket.IO >= 4.0

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

Support

For questions and support, please open an issue on GitHub.

Roadmap

  • [x] CLI tools for scaffolding
  • [x] Built-in rate limiting
  • [x] Auto-discovery of services
  • [x] Unified Client API (Decorative & Fluent)
  • [ ] Plugin system
  • [ ] Redis adapter for horizontal scaling
  • [ ] Prometheus metrics integration
  • [ ] WebSocket native support
  • [ ] Advanced validation with Zod

Built with ❤️ by the Nehonix Team