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

@fluojs/socket.io

v1.0.7

Published

Socket.IO v4 gateway adapter for Fluo applications, built on the shared runtime and websocket decorators.

Readme

@fluojs/socket.io

Socket.IO v4 gateway adapter for the fluo runtime.

Table of Contents

Installation

npm install @fluojs/core @fluojs/socket.io @fluojs/websockets socket.io

When to Use

Use this package when you need advanced real-time features like rooms, namespaces, broadcasting, and automatic reconnection provided by Socket.IO. This adapter integrates Socket.IO v4 into fluo's decorator-based architecture, sharing the same @WebSocketGateway core as raw websockets.

Quick Start

import { SocketIoModule, SOCKETIO_ROOM_SERVICE, type SocketIoRoomService } from '@fluojs/socket.io';
import { WebSocketGateway, OnMessage } from '@fluojs/websockets';
import { Inject, Module } from '@fluojs/core';

@Inject(SOCKETIO_ROOM_SERVICE)
@WebSocketGateway({ path: '/chat' })
class ChatGateway {
  constructor(private readonly rooms: SocketIoRoomService) {}

  @OnMessage('ping')
  handlePing(payload: unknown) {
    this.rooms.broadcastToRoom('chat:lobby', 'pong', payload);
  }
}

@Module({
  imports: [SocketIoModule.forRoot()],
  providers: [ChatGateway],
})
export class AppModule {}

Common Patterns

Room Management

The SocketIoRoomService provides a high-level API for managing client rooms and broadcasting.

this.rooms.joinRoom(socket.id, 'room:123');
this.rooms.broadcastToRoom('room:123', 'event', data);

Room helpers follow the shared WebSocketRoomService contract and add Socket.IO namespace awareness. Inside a gateway handler the current @WebSocketGateway({ path }) namespace is inferred automatically. When room helpers run outside gateway handler context, pass the namespace path explicitly so room operations target the intended Socket.IO namespace instead of a same-named room elsewhere.

this.rooms.broadcastToRoom('room:123', 'event', data, '/chat');
this.rooms.joinRoom(socketId, 'room:123', '/chat');

Accessing the Raw Server

You can inject the underlying Socket.IO Server instance for low-level control.

import { SOCKETIO_SERVER } from '@fluojs/socket.io';
import type { Server } from 'socket.io';

@Inject(SOCKETIO_SERVER)
class MyService {
  constructor(private readonly io: Server) {}
}

Keep raw server access narrow and use it for Socket.IO-specific semantics that the shared room contract intentionally does not wrap, such as multi-room native emits or volatile delivery:

@Inject(SOCKETIO_SERVER)
class SupportBroadcasts {
  constructor(private readonly io: Server) {}

  broadcastUrgent(message: string) {
    this.io.of('/support').to(['ticket:active', 'staff:updates']).emit('announcement', { message });
  }

  sendTyping(ticketId: string, userId: string) {
    this.io.of('/support').volatile.to(`ticket:${ticketId}`).emit('typing', { userId });
  }
}

Handler return values and ACK replies

Socket.IO gateway handlers use the shared @fluojs/websockets positional handler model: (payload, socket, request, acknowledgement). Return values are awaited for error containment and ordering, but they are ignored; fluo does not convert a returned value into an implicit Socket.IO emit or ACK reply. When a migrated NestJS @SubscribeMessage() handler previously returned an ACK payload, rewrite it to call the acknowledgement callback explicitly or inject SOCKETIO_SERVER and emit through the raw server boundary.

@OnMessage('ping')
handlePing(payload: unknown, _socket: Socket, _request: SocketIoHandshakeRequest, ack?: (response: unknown) => void) {
  ack?.({ event: 'pong', payload });
}

Auth guards, safe CORS defaults, and bounded payloads

Use SocketIoModule.forRoot(...) to require explicit namespace/message auth, keep CORS in a deny-by-default posture, and cap inbound Engine.IO payload size.

SocketIoModule.forRoot({
  auth: {
    connection({ socket }) {
      return socket.handshake.auth.token === 'demo-token'
        ? true
        : { message: 'Authentication required.' };
    },
    message({ payload }) {
      return payload === 'allowed'
        ? true
        : { message: 'Forbidden event.' };
    },
  },
  cors: {
    origin: ['https://app.example.com'],
  },
  engine: {
    maxHttpBufferSize: 65_536,
  },
});

When cors is omitted, @fluojs/socket.io defaults to { credentials: false, origin: false } so cross-origin exposure stays opt-in. When engine.maxHttpBufferSize is omitted, the adapter applies a bounded 1 MiB Engine.IO payload limit. Defaults also include buffer.maxPendingMessagesPerSocket: 128, buffer.overflowPolicy: 'drop-oldest', and shutdown.timeoutMs: 5000. Explicit engine.maxHttpBufferSize, buffer.maxPendingMessagesPerSocket, and shutdown.timeoutMs values must be positive integers; invalid explicit values fail during module registration instead of falling back to defaults.

Static @WebSocketGateway({ path }) namespaces are owned by fluo's gateway discovery and are not treated as Socket.IO dynamic child namespaces. The adapter keeps Socket.IO's cleanupEmptyChildNamespaces behavior disabled for those static namespaces. If application code creates dynamic child namespaces through raw SOCKETIO_SERVER access, that ownership and cleanup policy stays with the application-level Socket.IO integration.

During application shutdown, Socket.IO owns cleanup for connected Socket.IO clients, but the underlying HTTP server remains owned by the platform adapter or shared HTTP server integration that supplied it. The adapter detaches that HTTP server reference before io.close(...), so client cleanup still runs while Socket.IO does not close adapter-owned/shared HTTP listeners. If graceful Socket.IO close exceeds shutdown.timeoutMs, the adapter force-disconnects managed Socket.IO clients before clearing lifecycle state; if that force cleanup fails, the managed server reference and registries are retained for shutdown retry. Do not add a second manual socket-disconnect path around the same managed Socket.IO instance.

Guard contracts

auth.connection receives SocketIoConnectionGuardContext before namespace connect handlers run. auth.message receives SocketIoMessageGuardContext before message handlers run. Guards can return true, false, or a SocketIoGuardRejection with message, optional data, and optional disconnect; message rejections use ACK payloads shaped as { error, data }.

Bun-specific notes

The Bun path supports Socket.IO through @socket.io/bun-engine, but it requires static CORS shapes: no CORS delegate functions and no boolean entries inside cors.origin arrays. @WebSocketGateway({ serverBacked }) is not supported on Bun. Bun's HTTP request body limit (maxRequestBodySize) and WebSocket frame limit (websocket.maxPayloadLength) are separate host contracts; the adapter maps both from engine.maxHttpBufferSize so polling requests and websocket frames share the configured inbound payload bound.

Module registration

Register Socket.IO with SocketIoModule.forRoot(...).

Register Socket.IO through module imports in the owning module so namespace/message guards, CORS, and Engine.IO options stay configured in one place.

Public API Overview

  • SocketIoModule.forRoot(options): Main module for Socket.IO integration.
  • SocketIoModule.forRoot({ global, auth, cors, engine, ... }): Configures provider visibility, namespace/message guards, explicit CORS, and Engine.IO payload bounds.
  • SOCKETIO_SERVER: Token to inject the raw Socket.IO Server.
  • SOCKETIO_ROOM_SERVICE: Token to inject the SocketIoRoomService.
  • SocketIoRoomService: Shared room contract plus Socket.IO namespace-aware joinRoom, leaveRoom, broadcastToRoom, and getRooms helpers.
  • SocketIoLifecycleService: Lifecycle-backed implementation behind the server and room-service tokens; application code should usually inject SOCKETIO_SERVER or SOCKETIO_ROOM_SERVICE instead.
  • Types: SocketIoModuleOptions, SocketIoHandshakeRequest, SocketIoConnectionGuardContext, SocketIoConnectionGuard, SocketIoMessageGuardContext, SocketIoMessageGuard, SocketIoGuardRejection.

SocketIoModuleOptions covers global, auth, buffer, cors, engine, shutdown, and transports. global defaults to true, which keeps SOCKETIO_SERVER and SOCKETIO_ROOM_SERVICE visible across the app; set it to false when you want module-local provider visibility. A supported Node.js server-backed runtime adapter or the official Bun engine host is required; unsupported/noop adapters fail fast during bootstrap.

Supported Platforms

| Platform | Support | Note | | --- | --- | --- | | Node.js (Raw/Express/Fastify) | ✅ Full | Server-backed mode | | Bun | ✅ Full | Via @socket.io/bun-engine | | Deno | ❌ None | Not currently supported | | Workers | ❌ None | Not currently supported |

Example Sources

  • packages/socket.io/src/config.internal.test.ts
  • packages/socket.io/src/module.test.ts
  • packages/socket.io/src/public-surface.test.ts