{"id":31546837,"url":"https://github.com/admandev/socketio-decorator","last_synced_at":"2025-10-04T15:56:23.935Z","repository":{"id":250504378,"uuid":"832307269","full_name":"AdmanDev/socketio-decorator","owner":"AdmanDev","description":"This library allows you to use Socket.io with TypeScript decorators, simplifying the integration and usage of Socket.io in a TypeScript environment.","archived":false,"fork":false,"pushed_at":"2025-09-30T18:38:07.000Z","size":566,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-30T20:26:00.736Z","etag":null,"topics":["decorators","socket-io","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AdmanDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-22T18:47:31.000Z","updated_at":"2025-09-09T11:52:03.000Z","dependencies_parsed_at":"2024-08-03T10:41:40.288Z","dependency_job_id":"26b180d4-1f58-4a13-8910-b4493c3e5d99","html_url":"https://github.com/AdmanDev/socketio-decorator","commit_stats":null,"previous_names":["admandev/socketio-decorator"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/AdmanDev/socketio-decorator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdmanDev%2Fsocketio-decorator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdmanDev%2Fsocketio-decorator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdmanDev%2Fsocketio-decorator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdmanDev%2Fsocketio-decorator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AdmanDev","download_url":"https://codeload.github.com/AdmanDev/socketio-decorator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AdmanDev%2Fsocketio-decorator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278335450,"owners_count":25970129,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decorators","socket-io","typescript"],"created_at":"2025-10-04T15:56:21.934Z","updated_at":"2025-10-04T15:56:23.928Z","avatar_url":"https://github.com/AdmanDev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Socketio Decorator\n\nUse TypeScript decorators to simplify working with [Socket.IO](https://socket.io/) in your Node.js applications.\n\nThis library provides an elegant and declarative way to define Socket.IO event listeners, emitters, middlewares, and more — all using modern TypeScript decorators.\n\n## 📚 Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Decorators](#decorators)\n  - [Listening for Events](#listening-for-events)\n  - [Emitting Events](#emitting-events)\n  - [Parameter injection](#parameter-injection-decorators)\n  - [Other decorators](#other-decorators)\n- [Middlewares](#middlewares)\n  - [Server Middleware](#server-middleware)\n  - [Socket Middleware](#socket-middleware)\n  - [Namespace middleware](#namespace-middleware)\n  - [Error handling middleware](#error-handling-middleware)\n- [Data validation](#data-validation)\n  - [Setup](#setup)\n  - [Disable validation for a specific handler](#disable-validation-for-a-specific-handler)\n- [Hooks](#hooks)\n  - [UseIoServer hook](#useioserver-hook)\n  - [UseUserSocket hook](#useusersocket-hook)\n- [Dependency Injection](#dependency-injection)\n- [Migration 1.3.0 to 1.3.1](#migration-130-to-131)\n\n## Installation\n\nTo get started, follow these steps:\n\n1. Install the package:\n\n    ```bash\n    npm install @admandev/socketio-decorator socket.io\n    ```\n\n    \u003e [!NOTE]\n    \u003e ℹ️ Peer dependencies like `reflect-metadata` and `class-validator` may also be required depending on your use case (see [Data Validation](#data-validation)).\n\n2. Update your `tsconfig.json` to enable decorators:\n\n    ```json\n    {\n        \"compilerOptions\": {\n            \"module\": \"Node16 (or more recent)\",\n            \"experimentalDecorators\": true,\n            \"emitDecoratorMetadata\": true\n        }\n    }\n    ```\n\n## Quick Start\n\n1. **Create a Socket Controller**\n\n    ```typescript\n    import { Data, ServerOn, SocketOn, SocketEmitter } from \"@admandev/socketio-decorator\"\n    import { Socket } from \"socket.io\"\n\n    export class SocketController {\n        @ServerOn(\"connection\")\n        public onConnection(@CurrentSocket() socket: Socket) {\n            console.log(\"Socket connected with socket id\", socket.id)\n        }\n\n        @SocketOn(\"message\")\n        public onMessage(@CurrentSocket() socket: Socket, @Data() data: any) {\n            console.log(\"Message received:\", data, \"from socket id:\", socket.id)\n        }\n\n        // Async / Await is supported\n        @SocketOn(\"hello\")\n        @SocketEmitter(\"hello-back\") // Emit returned data as response, automatically\n        public async onHello() {\n            await something()\n            return {\n                message: \"Hello you\"\n            }\n        }\n\n    }\n    ```\n\n2. **Set Up the Server**\n\n   In your `app.ts` file, set up the server and use the Controller:\n\n    ```typescript\n    import { useSocketIoDecorator } from \"@admandev/socketio-decorator\"\n    import express from \"express\"\n    import http from \"http\"\n    import { Server } from \"socket.io\"\n    import { SocketController } from \"./SocketController\"\n\n    const app = express()\n    const server = http.createServer(app)\n\n    const io = new Server(server)\n\n    useSocketIoDecorator({\n        ioserver: io,\n        controllers: [SocketController],\n    })\n\n    server.listen(3000, () =\u003e {\n        console.log(\"Server running on port 3000\")\n    })\n    ```\n\n    You can also auto import controllers from a directory:\n\n    ```typescript\n    useSocketIoDecorator({\n        controllers: [path.join(__dirname, \"/controllers/*.js\")],\n        ...\n    })\n    ```\n\n## Decorators\n\n### Listening for Events\n\nThe following decorators can be used to listen for events:\n\n| Decorator               | Description                                              | Equivalent in Basic Socket.io       |\n|-------------------------|----------------------------------------------------------|-------------------------------------|\n| `@ServerOn(event: string)`     | Listens for server events.            | `io.on(event, callback)`            |\n| `@SocketOn(event: string)`     | Listens for events emitted by the client.             | `socket.on(event, callback)`        |\n| `@SocketOnce(event: string)`   | Listens for events emitted by the client only once.    | `socket.once(event, callback)`      |\n| `@SocketOnAny()`               | Listens for any event emitted by the client.           | `socket.onAny(callback)`            |\n| `@SocketOnAnyOutgoing()`       | Listens for any outgoing event.  | `socket.onAnyOutgoing(callback)`    |\n\n#### Example\n\n---\n\n##### @SeverOn(event: string)\n\n**Equivalent in basic Socket.io:** `io.on(event, callback)`\n\nListens for server events.\n\n**Usage** :\n\n```typescript\n@ServerOn(\"connection\")\npublic onConnection(@CurrentSocket() socket: Socket) {\n    console.log(\"Socket connected with socket id\", socket.id)\n}\n```\n\n---\n\n##### @SocketOn(event: string)\n\n**Equivalent in basic Socket.io:** `socket.on(event, callback)`\n\nListens for events emitted by the client.\n\n**Usage** :\n\n```typescript\n@SocketOn(\"message\")\npublic onMessage(@Data() data: any) {\n    console.log(\"Message received:\", data)\n}\n```\n\n---\n\n##### @SocketOnce(event: string)\n\n**Equivalent in basic Socket.io:** `socket.once(event, callback)`\n\nListens for events emitted by the client only once.\n\n**Usage** :\n\n```typescript\n@SocketOnce(\"message\")\npublic onMessage(@Data() data: any) {\n    console.log(\"Message received:\", data)\n}\n```\n\n---\n\n##### @SocketOnAny()\n\n**Equivalent in basic Socket.io:** `socket.onAny(callback)`\n\nListens for any event emitted by the client.\n\n**Usage** :\n\n```typescript\n@SocketOnAny()\npublic onAnyEvent(@EventName() event: string, @Data() data: any) {\n    console.log(\"Any event received:\", event, data)\n}\n```\n\n---\n\n##### @SocketOnAnyOutgoing()\n\n**Equivalent in basic Socket.io:** `socket.onAnyOutgoing(callback)`\n\nListens for any outgoing event\n\n**Usage** :\n\n```typescript\n@SocketOnAnyOutgoing()\npublic onAnyOutgoingEvent(@EventName() event: string, @Data() data: any) {\n    console.log(\"Any outgoing event received:\", event, data)\n}\n```\n\n### Emitting Events\n\nThe following decorators can be used to emit events to the client:\n\n| Decorator               | Description                                             | Equivalent in Basic Socket.io        |\n|-------------------------|---------------------------------------------------------|--------------------------------------|\n| `@ServerEmitter(event?: string, to?: string)`  | Emits event to all clients.                        | `io.emit(event, data)`               |\n| `@SocketEmitter(event:? string)`  | Emits event to specific client.                  | `socket.emit(event, data)`           |\n\n#### How to use\n\n1. **Basic usage**\n\n    The return value of the method is sent as the data of the event.\n\n    ```typescript\n    @SocketOn(\"get-latest-message\")\n    @SocketEmitter(\"message\")\n    public sendMessage() {\n        return { message: \"Hello, world!\" }\n    }\n    ```\n\n    The above code will emit a `message` event with the following data as response to the client :\n\n    ```json\n        {\n            \"message\": \"Hello, world!\"\n        }\n    ```\n\n2. **Emitting options**\n\n    - You can also specify options for the emitted event by returning an `EmitterOption` object.\n\n        ```typescript\n        import { EmitterOption, SocketEmitter } from \"@admandev/socketio-decorator\"\n        import { Socket } from \"socket.io\"\n\n        @SocketOn(\"chat-message\")\n        @SocketEmitter() // No event name specified\n        public sendMessage(@CurrentSocket() socket: Socket): EmitterOptions {\n            const isAllowedToSend = isUserAllowedToSendMessage(socket)\n            return new EmitterOption({\n                to: \"room1\",\n                message: \"newMessage\", // Event name set here\n                data: { message: \"Hello, world!\" },\n                disableEmit: !isAllowedToSend,\n            })\n        }\n        ```\n\n        The above code will emit a `newMessage` event to the `room1` room. The event will only be emitted if the `isUserAllowedToSendMessage` function returns `true`.\n.\n\n    - If you return an array of `EmitterOption` objects, an event will be emitted for each `EmitterOption` items.\n\n        ```typescript\n        @SocketOn(\"multiple-events\")\n        @ServerEmitter()\n        onMultipleEvents(@CurrentSocket() socket: Socket) {\n            socket.join(\"multiple-events\")\n            const events: EmitterOption[] = [\n                new EmitterOption({\n                    to: socket.id,\n                    message: \"event-1\",\n                    data: {\n                        message: \"This is event 1\"\n                    }\n                }),\n                new EmitterOption({\n                    to: \"multiple-events\",\n                    message: \"event-2\",\n                    data: {\n                        message: \"This is events-2\"\n                    }\n                }),\n            ]\n\n            return events\n        }\n        ```\n\n        The above code will emit two events: `event-1` and `event-2`.\n        `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.\n\n    **Emitter options**\n    The `EmitterOption` object has the following properties:\n\n    | Property | Type | Required | Description |\n    |----------|------|----------|-------------|\n    | `to`     | string | No (if the decorator provides this) | The target to emit the event to. |\n    | `message`| string | No (if the decorator provides this) | The event name to emit. |\n    | `data`   | any    | Yes | The data to emit. |\n    | `disableEmit` | boolean | No | If `true`, the event will not be emitted. |\n\n3. **Emitting falsy value**\n    If the method returns a falsy value (false, null undefined, 0, ...), the event will not be emitted.\n\n#### Examples\n\n---\n\n##### @ServerEmitter(event?: string, to?: string)\n\n**Equivalent in basic Socket.io:** `io.emit(event, data)` or `io.to(to).emit(event, data)`\n\nEmits events to all connected clients or to a specific room if the `to` parameter is provided.\n\n**Usages** :\n\n```typescript\n@ServerEmitter(\"newMessage\", \"room1\")\npublic sendMessage() {\n    return { message: \"Hello, world!\" }\n}\n```\n\n```typescript\n@ServerEmitter()\npublic sendMessage() {\n    return new EmitterOption({\n        to: \"room1\",\n        message: \"newMessage\",\n        data: { message: \"Hello, world!\" },\n    })\n}\n```\n\n---\n\n##### @SocketEmitter(event?: string)\n\n**Equivalent in basic Socket.io:** `socket.emit(event, data)`\n\nEmits event to the current client.\n\n\u003e [!WARNING]\n\u003e If the `event` parameter is not provided in decorator, it must be provided in the `EmitterOption` object.\n\n\u003e [!WARNING]\n\u003e This decorator must be used with a listener decorator (ServerOn or SocketOn) to work.\n\n**Usage** :\n\n```typescript\n@SocketOn(\"join-room\")\n@SocketEmitter(\"room-joined\")\npublic joinRoom(@CurrentSocket() socket: Socket) {\n    socket.join(\"myRoom\")\n    return {\n        info: `You have successfully joined room myRoom`,\n        roomId: \"myRoom\"\n    }\n}\n```\n\n```typescript\n@SocketOn(\"join-room\")\n@SocketEmitter()\npublic joinRoom(@CurrentSocket() socket: Socket) {\n    socket.join(\"myRoom\")\n    return new EmitterOption({\n        to: socket.id,\n        message: \"room-joined\",\n        data: {\n            info: `You have successfully joined room myRoom`,\n            roomId: \"myRoom\"\n        },\n    })\n}\n```\n\n### Parameter injection decorators\n\nThe following decorators can be used to inject parameters into the event handler methods:\n\n| Decorator | Description                                              |\n|-----------|----------------------------------------------------------|\n| `@CurrentSocket()` | Injects the current socket instance that is handling the message. |\n| `@Data(dataIndex?: number)` | Injects the data sent by the client                 |\n| `@EventName()` | Injects the name of the event message that triggered the handler. |\n| `@CurrentUser()` | Injects the current user object. |\n\n#### Examples\n\n---\n\n##### @CurrentSocket()\n\nInjects the current socket instance that is handling the message.\n\n**Usage** :\n\n```typescript\n@SocketOn(\"joinGame\")\npublic onJoinGame(@CurrentSocket() socket: Socket) {\n    socket.join(\"gameRoom\")\n}\n```\n\n---\n\n##### @Data(dataIndex?: number)\n\nInjects the data sent by the client.\n\n**Usage** :\n\n```typescript\n@SocketOn(\"message\")\npublic onMessage(@Data() data: MessageData) {\n    console.log(\"Message received:\", data.message)\n}\n```\n\nYou can also specify the index of the data in the socket message if you want to inject a specific part of the data:\n\n```typescript\n@SocketOn(\"chat-message\")\npublic onChatMessage(@Data(0) message: string, @Data(1) roomId: string) {\n    console.log(`Received message: \"${message}\" for room: ${roomId}`)\n}\n```\n\nThis is useful when the client sends multiple arguments:\n\n```typescript\n// Client side\nsocket.emit(\"chat-message\", \"Hello everyone!\", \"gaming-lobby\")\n```\n\n---\n\n##### @EventName()\n\nInjects the name of the event message that triggered the handler.\n\n**Usage** :\n\n```typescript\n@SocketOn(\"user-joined\")\n@SocketOn(\"user-left\")\npublic trackUserActivity(@EventName() event: string) {\n    const action = event === \"user-joined\" ? \"joined the chat\" : \"left the chat\" \n\n    console.log(`User ${action}`)\n}\n```\n\n---\n\n##### @CurrentUser()\n\nInjects the current user object into an event handler parameter.\n\n**Usage** :\n\n1. **Create the `currentUserProvider`**\n\n   In the `app.ts` file, create a function that returns the current user object:\n\n    ```typescript\n    useSocketIoDecorator({\n        ...,\n        currentUserProvider: async (socket: Socket) =\u003e {\n            const token = socket.handshake.auth.token\n            return await userServices.getUserByToken(token)\n        },\n    })\n    ```\n\n2. **Use the `CurrentUser` decoratoar**\n\n   In the event handler, use the `CurrentUser` decorator to get the current user object:\n\n    ```typescript\n    import { CurrentUser, SocketOn } from \"@admandev/socketio-decorator\"\n\n    @SocketOn(\"message\")\n    public onMessage(@CurrentUser() user: User) {\n        console.log(\"Message received from user:\", user.name)\n    }\n    ```\n\n### Other decorators\n\n| Decorator | Description                                              |\n|-------------------------|----------------------------------------------------------|\n| `@UseSocketMiddleware(...ISocketMiddleware[])` | Applies one or more socket middleware to the event handler or controller class. |\n| `@SocketNamespace(namespace: string)` | Defines a namespace for a socket controller |\n| `@MiddlewareOption(options: MiddlewareOptionType)` | Applies options to a middleware. |\n\n#### Examples\n\n---\n\n##### @UseSocketMiddleware(...ISocketMiddleware[])\n\nApplies one or more socket middlewares to the event handler or controller class.\n\n**Usage** :\n\nFirst create a [socket middleware](#socket-middleware) before choosing one of next steps.\n\n1. **Use it on an event handler method**:\n\n    ```typescript\n    @SocketOn(\"message\")\n    @UseSocketMiddleware(MyMiddleware1, MyMiddleware2)\n    public onMessage() {\n        console.log(\"Message received\")\n    }\n    ```\n\n    In this case, the `MyMiddleware1` and `MyMiddleware2` will be called before the `onMessage` event handler is executed.\n\n2. **Use it on a controller class**:\n\n    ```typescript\n    @UseSocketMiddleware(MyMiddleware)\n    export class MyController {\n        @SocketOn(\"event1\")\n        public onEvent1() {\n            console.log(\"Event 1 received\")\n        }\n\n        @SocketOn(\"event2\")\n        public onEvent2() {\n            console.log(\"Event 2 received\")\n        }\n    }\n    ```\n\n    In this case, the `MyMiddleware` will be applied to all event handlers in the `MyController` class.\n\n    \u003e [!NOTE]\n    \u003e This decorator is applied to socket listener handlers only (`@SocketOn`, `@SocketOnce`, `@SocketOnAny`, ...).\n    \u003e It does not apply to server listeners (`@ServerOn`) or emitters.\n\n---\n\n##### @SocketNamespace(namespace: string)\n\n**Equivalent in basic Socket.io:** `io.of(namespace)`\n\nDefines a namespace for a socket controller. All socket events in this controller will be handled within this namespace. Learn more about [Socket.IO namespaces](https://socket.io/docs/v4/namespaces/).\n\n**Usage** :\n\n```typescript\n@SocketNamespace(\"/my-namespace\")\nexport class MyNamespaceController {\n    @SocketOn(\"message\")\n    public onMessage(@Data() data: MessageRequest) {\n        console.log(\"Message in my-namespace\", data.message)\n    }\n}\n```\n\n\u003e [!WARNING]\n\u003e The namespace must start with \"/\" or it will throw a `SiodDecoratorError`.\n\n---\n\n##### @MiddlewareOption(options: MiddlewareOptionType)\n\nApplies options to a middleware.\n\n**Middleware options**\n\n| Property | Type | Description |\n|----------|------|-------------|\n| [`namespace`](#namespace-middleware) | string | The namespace to which the middleware should be applied. |\n\n## Middlewares\n\nYou can use middlewares to execute code before  an event is handled. Middlewares can be used to perform tasks such as authentication or logging.\n\n### Server Middleware\n\nA Server Middleware is executed for each incoming connection.\n\n1. **Create a Middleware**\n\n    ```typescript\n    export class MyServerMiddleware implements IServerMiddleware {        \n        use(socket: Socket, next: (err?: unknown) =\u003e void) {\n            console.log(\"You can perform tasks here before the event is handled\")\n            next()\n        }\n    }\n    ```\n\n    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.\n\n2. **Register the Middleware**\n\n   Update the `app.ts` file to register the middleware:\n\n    ```typescript\n    useSocketIoDecorator({\n        ...,\n        serverMiddlewares: [MyServerMiddleware], // Add the middleware here\n    })\n    ```\n\n### Socket Middleware\n\nA Socket Middleware is like Server Middleware but it is called for each incoming packet.\n\n1. **Create a Middleware**\n\n    ```typescript\n    import { ISocketMiddleware } from \"@admandev/socketio-decorator\"\n    import { Event, Socket } from \"socket.io\"\n\n    export class MySocketMiddleware implements ISocketMiddleware {\n        use(socket: Socket, [event, ...args]: Event, next: (err?: Error) =\u003e void): void {\n            console.log(`MySocketMiddleware triggered from ${event} event`)\n            next()\n        }\n    }\n    ```\n\n2. **Use the Middleware**\n\n    Now you can use the socket middleware in 2 ways:\n\n    - **Globally**: This will apply the middleware to all events in your application.\n    Update the `app.ts` file to register the middleware:\n\n        ```typescript\n        useSocketIoDecorator({\n            ...,\n            socketMiddlewares: [MySocketMiddleware], // Add the middleware here\n        })\n        ```\n\n    - **Per event**: You can also use the middleware for a specific event by using the [@UseSocketMiddleware decorator](#other-decorators).\n\n### Namespace middleware\n\nYou can scope a middleware to a specific namespace using the `@MiddlewareOption` decorator. This is particularly useful when using the `@SocketNamespace` decorator to organize your controllers by namespaces.\n\n```typescript\n@MiddlewareOption({ namespace: \"/orders\" })\nclass OrderMiddleware implements IServerMiddleware {\n    public use(socket: Socket, next: (err?: unknown) =\u003e void) {\n        // This middleware will only be executed for connections to the \"/orders\" namespace\n        console.log(\"New connection to /orders namespace\")\n        next()\n    }\n}\n```\n\nIn this example:\n\n- The `OrderMiddleware` will only be executed for connections to the \"/orders\" namespace\n- Other namespaces (or the default namespace) will not trigger this middleware\n- This works for both Server and Socket middlewares (globally only)\n\n### Error handling middleware\n\nYou can create a middleware to handle errors that occur during event handling and above middlewares.\n\n1. **Create an Error Middleware**\n\n    ```typescript\n    import { IErrorMiddleware } from \"@admandev/socketio-decorator\"\n    import { Socket } from \"socket.io\"\n\n    export class MyErrorMiddleware implements IErrorMiddleware{\n        handleError (error: any, socket?: Socket) {\n            // Handle the error here\n            console.log('Error middleware: ', error)\n        }\n    }\n    ```\n\n2. **Register the Middleware**\n\n    Update the `app.ts` file to register the middleware:\n\n     ```typescript\n     useSocketIoDecorator({\n          ...,\n          errorMiddleware: MyErrorMiddleware, // Add the unique error middleware here\n     })\n     ```\n\n## Data validation\n\nYou 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.\n\n### Setup\n\n1. **Install the following libraries**\n\n    ```bash\n    npm install class-validator class-transformer reflect-metadata\n    ```\n\n2. **Import the `reflect-metadata` library**\n  \n    Add the following line at the top of your `app.ts` file:\n\n    ```typescript\n    import \"reflect-metadata\"\n     ```\n\n3. **Be sure to enable the `emitDecoratorMetadata` option in your `tsconfig.json` file**\n\n    ```json\n    {\n        \"compilerOptions\": {\n            \"emitDecoratorMetadata\": true\n        }\n    }\n    ```\n\n4. **Enable the validation option in the `useSocketIoDecorator` config**\n\n    ```typescript\n    useSocketIoDecorator({\n        ...,\n        dataValidationEnabled: true\n    })\n    ```\n\n5. **Create and use a class with validation rules**\n\n    ```typescript\n    import { IsString } from \"class-validator\"\n\n    export class MessageData {\n        @IsString()\n        @IsNotEmpty()\n        message: string\n    }\n    ```\n\n    Use the class in the event handler:\n\n    ```typescript\n    @SocketOn(\"message\")\n    public onMessage(@Data() data: MessageData) {\n        console.log(\"Message received:\", data.message)\n    }\n    ```\n\n    If the data does not match the validation rules, an error will be thrown before the event handler is called.\n\n\u003e [!WARNING]\n\u003e We recommend using the [error handling middleware](#error-handling-middleware) to catch and handle validation errors.\n\n### Disable validation for a specific handler\n\nYou can disable validation for a specific handler by setting the `disableDataValidation` option to `true`:\n\n```typescript\n@SocketOn(\"message\", { disableDataValidation: true })\npublic onMessage(@Data() data: MessageData) {\n    ...\n}\n```\n\n#### Default enabled validation\n\nData validation works only on socket listeners (not server listeners or emitters).\n\nHere is the default value for the `disableDataValidation` option:\n\n- `@SocketOn` - `false`\n- `@SocketOnce` - `false`\n- `@SocketOnAny` - `true` - If you want to validate the data, you need to set the option to `false`\n- `@SocketOnAnyOutgoing` - `true` because it is not an incoming event from the client\n\n### Learn more about data validation\n\nFor more information on data validation, see the [class-validator documentation](https://github.com/typestack/class-validator).\n\n## Hooks\n\nHooks in Socketio Decorator are functions that provides some data.\n\n### UseIoServer hook\n\nThe `useIoServer` is the simpliest hook that provides the `io` socketio server object.\n\n```typescript\nimport { useIoServer } from \"@admandev/socketio-decorator\"\nimport { Server } from \"socket.io\"\n\nconst io: Server = useIoServer()\n```\n\n---\n\n### UseUserSocket hook\n\nThe `useUserSocket` hook allows you to retrieve a specific connected socket instance based on a search argument (e.g., user ID).\n\n1. **Setup the `searchUserSocket` function**\n\n   In the `app.ts` file, provide a function that searches for a user socket based on an argument:\n\n    ```typescript\n    useSocketIoDecorator({\n        ...,\n        // Here we decide that the search argument is the user ID but you can use any other argument type\n        searchUserSocket: async (userId: string) =\u003e {\n            const allSockets = Array.from(io.sockets.sockets.values())\n            return allSockets.find(socket =\u003e socket.user.id === userId) || null\n        },\n    })\n    ```\n\n2. **Use the `useUserSocket` hook anywhere**\n\n    ```typescript\n    import { useUserSocket } from \"@admandev/socketio-decorator\"\n    import { Socket } from \"socket.io\"\n\n    const userSocket: Socket | null = await useUserSocket(userId)\n    ```\n\n## Dependency Injection\n\nSocketio Decorator supports dependency injection using a DI library. You can inject services into your controllers and middlewares.\n\nTo allow Socketio Decorator to work with your DI system, you need to provide the `Container` object to the `useSocketIoDecorator` options.\n\n```typescript\nimport { Container } from \"typedi\"\n\nuseSocketIoDecorator({\n    ...,\n    iocContainer: Container,\n})\n```\n\n\u003e [!NOTE]\n\u003e Your Container object must provide the `get` method to resolve dependencies.\n\n## 🧪 Example project\n\nCheck out the full example using Express:\n👉 [Example on GitHub](https://github.com/AdmanDev/socketio-decorator/tree/master/examples/nodeexample)\n\n## 🛠 Troubleshooting \u0026 Help\n\nIf you run into any issues or have suggestions, feel free to open an issue on GitHub:\n\n🔗 [Socket.io Decorator Issues](https://github.com/AdmanDev/socketio-decorator/issues)\n\nThank you for using Socketio Decorator\n\n## Migration 1.3.0 to 1.3.1+\n\nStarting from version 1.3.1, you need to use the parameter injection decorators (`@CurrentSocket()`, `@Data()`, `@EventName()`) to access the socket, data, and event name in your handlers:\n\n```typescript\n// Before (1.3.0)\n@SocketOn(\"message\")\npublic onMessage(socket: Socket, data: any) {\n    console.log(\"Message from:\", socket.id, \"data:\", data)\n}\n\n// After (1.3.1+)\n@SocketOn(\"message\")\npublic onMessage(@CurrentSocket() socket: Socket, @Data() data: any) {\n    console.log(\"Message from:\", socket.id, \"data:\", data)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadmandev%2Fsocketio-decorator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadmandev%2Fsocketio-decorator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadmandev%2Fsocketio-decorator/lists"}