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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@admandev/socketio-decorator

v1.2.3

Published

This library allows you to use Socket.io with TypeScript decorators, simplifying the integration and usage of Socket.io in a TypeScript environment.

Downloads

49

Readme

Socketio Decorator

This library allows you to use Socket.io with TypeScript decorators, simplifying the integration and usage of Socket.io in a TypeScript environment.

Table of Contents

Installation

To get started, follow these steps:

  1. Install the package:

    npm install @admandev/socketio-decorator
  2. Install the required peer dependencies for Socket.io:

    npm install socket.io
  3. Update your tsconfig.json to enable decorators:

    {
        "compilerOptions": {
            "module": "Node16",
            "experimentalDecorators": true,
            "emitDecoratorMetadata": true
        }
    }

Usage

  1. Create a Socket Controller

    Create a file named SocketController.ts with the following content:

    import { ServerOn, SocketOn, SocketEmitter } from "@admandev/socketio-decorator";
    import { Socket } from "socket.io";
    
    export class SocketController {
        @ServerOn("connection")
        public onConnection(socket: Socket) {
            console.log("Socket connected with socket id", socket.id);
        }
    
        @SocketOn("message")
        public onMessage(socket: Socket, data: any) {
            console.log("Message received:", data);
        }
    
        // Async / Await is supported
        @SocketOn("hello")
        @SocketEmitter("hello-back")
        public async onHello() {
            await something()
            return {
                message: "Hello you"
            }
        }
    
    }

    The SocketController class contains 3 methods: onConnection, onMessage and onHello.

    The onConnection method listens for the socket connection event. The onMessage method listens for a message event and logs the received data. The onHello method listens for a hello event, waits for 2 seconds, and emits a hello-back event with the message "Hello you".

  2. Set Up the Server

    Create a file named app.ts with the following content:

    import { useSocketIoDecorator } from "@admandev/socketio-decorator";
    import express from "express";
    import http from "http";
    import { Server } from "socket.io";
    import { SocketController } from "./SocketController";
    
    const app = express();
    const server = http.createServer(app);
    
    const io = new Server(server);
    
    useSocketIoDecorator({
        ioserver: io,
        controllers: [SocketController],
    });
    
    server.listen(3000, () => {
        console.log("Server running on port 3000");
    });
  3. Run the Server

    You can now test the server by connecting with Postman or another WebSocket client and sending a message event. You should see the message logged in the console.

Decorators

Listening for Events

The following decorators can be used to listen for events:

| Decorator | Description | Equivalent in Basic Socket.io | |-------------------------|----------------------------------------------------------|-------------------------------------| | @ServerOn(event: string) | Listens for server events. | io.on(event, callback) | | @SocketOn(event: string) | Listens for events emitted by the client. | socket.on(event, callback) | | @SocketOnce(event: string) | Listens for events emitted by the client only once. | socket.once(event, callback) | | @SocketOnAny() | Listens for any event emitted by the client. | socket.onAny(callback) | | @SocketOnAnyOutgoing() | Listens for any outgoing event. | socket.onAnyOutgoing(callback) |

Example


@SeverOn(event: string)

Equivalent in basic Socket.io: io.on(event, callback)

Listens for server events.

Usage :

@ServerOn("connection")
public onConnection(socket: Socket) {
    console.log("Socket connected with socket id", socket.id);
}

@SocketOn(event: string)

Equivalent in basic Socket.io: socket.on(event, callback)

Listens for events emitted by the client.

Usage :

@SocketOn("message")
public onMessage(socket: Socket, data: any) {
    console.log("Message received:", data);
}

@SocketOnce(event: string)

Equivalent in basic Socket.io: socket.once(event, callback)

Listens for events emitted by the client only once.

Usage :

@SocketOnce("message")
public onMessage(socket: Socket, data: any) {
    console.log("Message received:", data);
}

@SocketOnAny()

Equivalent in basic Socket.io: socket.onAny(callback)

Listens for any event emitted by the client.

Usage :

@SocketOnAny()
public onAnyEvent(socket: Socket, event: string, data: any) {
    console.log("Any event received:", event, data);
}

@SocketOnAnyOutgoing()

Equivalent in basic Socket.io: socket.onAnyOutgoing(callback)

Listens for any outgoing event

Usage :

@SocketOnAnyOutgoing()
public onAnyOutgoingEvent(socket: Socket, event: string, data: any) {
    console.log("Any outgoing event received:", event, data);
}

Emitting Events

The following decorators can be used to emit events to the client:

| Decorator | Description | Equivalent in Basic Socket.io | |-------------------------|---------------------------------------------------------|--------------------------------------| | @ServerEmitter(event?: string, to?: string) | Emits event from the server. | io.emit(event, data) | | @SocketEmitter(event:? string) | Emits event from the socket. | socket.emit(event, data) |

How to use

  1. Basic usage

    The return value of the method is sent as the data of the event.

    @SocketOn("get-latest-message")
    @SocketEmitter("message")
    public sendMessage() {
        return { message: "Hello, world!" }
    }

    The above code will emit a message event with the following data:

        {
            "message": "Hello, world!"
        }
  2. Emitting options

    • You can also specify options for the emitted event by returning an EmitterOption object.

      import { EmitterOption, SocketEmitter } from "@admandev/socketio-decorator"
      import { Socket } from "socket.io"
      
      @SocketOn("get-latest-message")
      @SocketEmitter() // No event name specified
      public sendMessage(socket: Socket): EmitterOptions {
          const isAllowedToSend = isUserAllowedToSendMessage(socket)
          return new EmitterOption({
              to: "room1",
              message: "newMessage",
              data: { message: "Hello, world!" },
              disableEmit: !isAllowedToSend,
          })
      }

      The above code will emit a newMessage event to the room1 room. The event will only be emitted if the isUserAllowedToSendMessage function returns true. .

    • If you return an array of EmitterOption objects, an event will be emitted for each EmitterOption items.

      @SocketOn("multiple-events")
      @ServerEmitter()
      onMultipleEvents(socket: Socket) {
          socket.join("multiple-events");
          const events: EmitterOption[] = [
              new EmitterOption({
                  to: socket.id,
                  message: "event-1",
                  data: {
                      message: "This is event 1"
                  }
              }),
              new EmitterOption({
                  to: "multiple-events",
                  message: "event-2",
                  data: {
                      message: "This is events-2"
                  }
              }),
          ]
      
          return events
      }

      The above code will emit two events: event-1 and event-2. event-1 will be emitted to the client with the id of the socket and event-2 will be emitted to the multiple-events room.

    Emitter options The EmitterOption object has the following properties:

    | Property | Type | Required | Description | |----------|------|----------|-------------| | to | string | No (if the decorator provides this) | The target to emit the event to. | | message| string | No (if the decorator provides this) | The event name to emit. | | data | any | Yes | The data to emit. | | disableEmit | boolean | No | If true, the event will not be emitted. |

  3. Emitting falsy value If the method returns a falsy value (false, null undefined, 0, ...), the event will not be emitted.

Examples


@ServerEmitter(event?: string, to?: string)

Equivalent in basic Socket.io: io.emit(event, data) or io.to(to).emit(event, data)

Emits events to all connected clients or to a specific room if the to parameter is provided.

[!WARNING] This decorator must be used with a listener decorator (ServerOn or SocketOn) to work.

Usages :

@SocketOn("message")
@ServerEmitter("newMessage", "room1")
public sendMessage() {
    return { message: "Hello, world!" }
}
@SocketOn("message")
@ServerEmitter()
public sendMessage() {
    return new EmitterOption({
        to: "room1",
        message: "newMessage",
        data: { message: "Hello, world!" },
    })
}

@SocketEmitter(event?: string)

Equivalent in basic Socket.io: socket.emit(event, data)

Emits event to the current client.

[!WARNING] If the event parameter is not provided in decorator, it must be provided in the EmitterOption object.

[!WARNING] This decorator must be used with a listener decorator (ServerOn or SocketOn) to work.

Usage :

@SocketOn("get-user")
@SocketEmitter("get-user-resp")
public getUser(socket: Socket) {
    return useCurrentUser(socket)
}
@SocketOn("get-user")
@SocketEmitter()
public getUser(socket: Socket) {
    return new EmitterOption({
        to: socket.id,
        message: "get-user-resp",
        data: useCurrentUser(socket),
    })
}

Middlewares

You can use middlewares to execute code before an event is handled. Middlewares can be used to perform tasks such as authentication or logging.

Server Middleware

A Server Middleware is executed for each incoming connection.

  1. Create a Middleware

    Create a file named MyServerMiddleware.ts and create a class that implements the IServerMiddleware interface:

    export class MyServerMiddleware implements IServerMiddleware {        
        use(socket: Socket, next: (err?: unknown) => void) {
            console.log("You can perform tasks here before the event is handled")
            next()
        }
    }

    The use method is called before any event is handled. You can perform any tasks here and call next() to proceed with the event handling.

  2. Register the Middleware

    Update the app.ts file to register the middleware:

    useSocketIoDecorator({
        ...,
        serverMiddlewares: [MyServerMiddleware], // Add the middleware here
    })

Socket Middleware

A Socket Middleware is like Server Middleware but it is called for each incoming packet.

  1. Create a Middleware

    Create a file named MySocketMiddleware.ts and create a class that implements the ISocketMiddleware interface:

    import { ISocketMiddleware } from "@admandev/socketio-decorator"
    import { Event } from "socket.io"
    
    export class MySocketMiddleware implements ISocketMiddleware {
        use([event, ...args]: Event, next: (err?: Error) => void): void {
            console.log(`MySocketMiddleware triggered from ${event} event`)
            next()
        }
    }
  2. Register the Middleware

    Update the app.ts file to register the middleware:

    useSocketIoDecorator({
        ...,
        socketMiddlewares: [MySocketMiddleware], // Add the middleware here
    })

Error handling middleware

You can create a middleware to handle errors that occur during event handling and above middlewares.

  1. Create an Error Middleware

    Create a file named MyErrorMiddleware.ts and create a class that implements the IErrorMiddleware interface:

    import { IErrorMiddleware } from "@admandev/socketio-decorator";
    import { Socket } from "socket.io";
    
    export class MyErrorMiddleware implements IErrorMiddleware{
        handleError (error: any, socket?: Socket) {
            // Handle the error here
            console.log('Error middleware: ', error);
        }
    }
  2. Register the Middleware

    Update the app.ts file to register the middleware:

    useSocketIoDecorator({
         ...,
         errorMiddleware: MyErrorMiddleware, // Add the unique error middleware here
    })

Data validation

You can use the class-validator library to validate the data received from the client and be sure that required fields are present and have the correct type.

Setup

  1. Install the following libraries

    npm install class-validator class-transformer reflect-metadata
  2. Import the reflect-metadata library

    Add the following line at the top of your app.ts file:

    import "reflect-metadata"
  3. Be sure to enable the emitDecoratorMetadata option in your tsconfig.json file

    {
        "compilerOptions": {
            "emitDecoratorMetadata": true
        }
    }
  4. Enable the validation option in the useSocketIoDecorator config

    useSocketIoDecorator({
        ...,
        dataValidationEnabled: true
    })
  5. Create and use a class with validation rules

    import { IsString } from "class-validator"
    
    export class MessageData {
        @IsString()
        message: string
    }

    Use the class in the event handler:

    @SocketOn("message")
    public onMessage(socket: Socket, data: MessageData) {
        console.log("Message received:", data.message)
    }

    If the data does not match the validation rules, an error will be thrown before the event handler is called.

[!WARNING] We recommend using the error handling middleware to catch and handle validation errors.

Disable validation for a specific handler

You can disable validation for a specific handler by setting the disableDataValidation option to true:

@SocketOn("message", { disableDataValidation: true })
public onMessage(socket: Socket, data: MessageData) {
    ...
}

Default enabled validation

Data validation works only on socket listeners (not server listeners or emitters).

Here is the default value for the disableDataValidation option:

  • @SocketOn - false
  • @SocketOnce - false
  • @SocketOnAny - true - If you want to validate the data, you need to set the option to false
  • @SocketOnAnyOutgoing - true because it is not an incoming event from the client

Learn more about data validation

For more information on data validation, see the class-validator documentation.

Hooks

Hooks in Socketio Decorator are functions that provides some data.

UseIoServer hook

The useIoServer is the simpliest hook that provides the io socketio server object.

import { useIoServer } from "@admandev/socketio-decorator"
import { Server } from "socket.io"

const io: Server = useIoServer()

UseCurrentUser hook

The useCurrentUser hook provides the current user object. This hook is useful when you want to get the current user object in the event handler.

  1. Create the currentUserProvider

    In the app.ts file, create a function that returns the current user object:

    useSocketIoDecorator({
        ...,
        currentUserProvider: (socket: Socket) => {
            const token = socket.handshake.auth.token
            const user = userServices.getUserByToken(token)
            return user
        },
    })
  2. Use the useCurrentUser hook

    In the event handler, use the useCurrentUser hook to get the current user object:

    import { useCurrentUser, SocketOn } from "@admandev/socketio-decorator"
    import { Socket } from "socket.io"
    
    @SocketOn("message")
    public onMessage(socket: Socket, data: any) {
        const user = useCurrentUser(socket)
        console.log("Message received from user:", user)
    }

Dependency Injection

Socketio Decorator supports dependency injection using a DI library. You can inject services into your controllers and middlewares.

To allow Socketio Decorator to work with your DI system, you need to provide the Container object to the useSocketIoDecorator options.

import { Container } from "typedi"

useSocketIoDecorator({
    ...,
    iocContainer: Container,
})

Note: Your Container object must provide the get method to resolve dependencies.

Note 2: Your controllers and middlewares must be registered in the DI container.

Important: The iocContainer option is optional. If you don't provide it, Socketio Decorator will create a new instance of the controllers or middlewares and keep them in memory.

Sample project

You can find a sample project using express here.

Thanks

Thank you for using Socketio Decorator. If you have any questions or suggestions, feel free to open an issue on the GitHub repository.