Nourished Personal Mucus

    nestjs-websocket
    TypeScript icon, indicating that this package has built-in type declarations

    0.1.3 • Public • Published

    NestJS-Websocket

    npm CircleCI Coverage Status vulnerabilities supported platforms

    Websocket Client for NestJS based on ws

    Install

    npm i nestjs-websocket

    Register module

    Configuration params

    nestjs-websocket can be configured with this options:

    /**
     * WebSocket Client options
     * @see {@link https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocket}
     */
    interface WebSocketModuleOptions {
      /**
       * Required parameter a URL to connect to.
       * such as http://localhost:3000 or wss://localhost:3000.
       */
      url: string | URL;
    
      /**
       * Optional parameter a list of subprotocols.
       */
      protocols?: string | string[]
      
      /**
       * Optional parameter a client or http request options.
       */
      options?: ClientOptions | ClientRequestArgs
    }

    Synchronous configuration

    Use WebSocketModule.forRoot method with Options interface:

    import { WebSocketModule } from 'nestjs-websocket'
    
    @Module({
      imports: [
        WebSocketModule.forRoot({
          url: 'ws://localhost:3000',
          protocols: ['foo', 'bar'],
          options: {
            followRedirects: false,
            handshakeTimeout: 10000,
            maxPayload: 2000000,
            maxRedirects: 10,
            origin: 'http:/example.com',
            perMessageDeflate: false,
            protocolVersion: 1,
            skipUTF8Validation: false,
          },
        }),
      ],
      ...
    })
    class MyModule {}

    Asynchronous configuration

    With WebSocketModule.forRootAsync you can, for example, import your ConfigModule and inject ConfigService to use it in useFactory method.

    useFactory should return object with Options interface

    Here's an example:

    import { Module, Injectable } from '@nestjs/common'
    import { WebSocketModule } from 'nestjs-websocket'
    
    @Injectable()
    class ConfigService {
      public readonly url = 'ws://localhost:3000'
    }
    
    @Module({
      providers: [ConfigService],
      exports: [ConfigService]
    })
    class ConfigModule {}
    
    @Module({
      imports: [
        WebSocketModule.forRootAsync({
          imports: [ConfigModule],
          inject: [ConfigService],
          useFactory: (config: ConfigService) => {
            return {
              url: config.url,
            }
          },
        }),
      ],
      ...
    })
    class MyModule {}

    Or you can just pass ConfigService to providers, if you don't have any ConfigModule:

    import { Module, Injectable } from '@nestjs/common'
    import { WebSocketModule } from 'nestjs-websocket'
    
    @Injectable()
    class ConfigService {
      public readonly url = 'ws://localhost:3000'
    }
    
    @Module({
      imports: [
        WebSocketModule.forRootAsync({
          providers: [ConfigService],
          inject: [ConfigService],
          useFactory: (config: ConfigService) => {
            return {
              url: config.url,
            }
          },
        }),
      ],
      controllers: [TestController]
    })
    class TestModule {}

    WebSocketClient

    WebSocketClient implements a WebSocket. So if you are familiar with it, you are ready to go.

    import { Injectable } from '@nestjs/common'
    import {
      InjectWebSocketProvider,
      WebSocketClient,
      OnOpen,
      OnMessage,
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      private data: Record<any, any> = {}
    
      constructor(
        @InjectWebSocketProvider()
        private readonly ws: WebSocketClient,
      ) {}
    
      @OnOpen()
      onOpen() {
        this.ws.send(JSON.stringify(eventData))
      }
    
      @OnMessage()
      message(data: WebSocketClient.Data) {
        this.data = JSON.parse(data.toString())
      }
    
      async getData(): Promise<Record<any, any>> {
        return this.data
      }
    }

    Websocket Events

    EventListener

    @EventListener decorator will handle any event emitted from websocket server.

    import { Injectable } from '@nestjs/common'
    import { ClientRequest, IncomingMessage } from 'http'
    import {
      EventListener
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      @EventListener('open')
      open() {
        console.log('The connection is established.')
      }
      
      @EventListener('ping')
      ping(data: Buffer) {
        console.log(`A ping ${data.toString()} is received from the server.`)
      }
      
      @EventListener('unexpected-response')
      unexpectedResponse(request: ClientRequest, response: IncomingMessage) {
        console.log(`The server response ${response} is not the expected one.`)
      }
      
      @EventListener('upgrade')
      upgrade(response: IncomingMessage) {
        console.log(`Response headers ${response} are received from the server as part of the handshake.`)
      }
    }

    OnOpen

    @OnOpen is a shortcut for @EventListener('open'). Event emitted when the connection is established.

    import { Injectable } from '@nestjs/common'
    import {
      OnOpen
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      @OnOpen()
      open() {
        console.log('The connection is established.')
      }
    }

    OnClose

    @OnClose is a shortcut for @EventListener('close') Event emitted when the connection is closed. code property is a numeric value for status code explaining why the connection has been closed. reason is a Buffer containing a human-readable string explaining why the connection has been closed.

    import { Injectable } from '@nestjs/common'
    import {
      OnClose
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      @OnClose()
      close(code: number, reason: string) {
        console.log(`The connection is closed. Reason: ${code} - ${reason}`)
      }
    }

    OnError

    @OnError is a shortcut for @EventListener('error'). Event emitted when an error occurs. Errors may have a .code property.

    import { Injectable } from '@nestjs/common'
    import {
      OnError
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      @OnError()
      error(err: Error) {
        console.log(`An error occurs: ${err}`)
      }
    }

    OnMessage

    @OnMessage is a shortcut for @EventListener('message'). Event emitted when a message is received. data is the message content.

    import { Injectable } from '@nestjs/common'
    import {
      OnMessage
    } from 'nestjs-websocket';
    
    @Injectable()
    class TestService {
      @OnMessage()
      message(data: WebSocketClient.Data) {
        console.log(`Data received: ${JSON.parse(data.toString())}`)
      }
    }

    Testing a class that uses @InjectWebSocketProvider

    This package exposes a getWebSocketToken() function that returns a prepared injection token based on the provided context. Using this token, you can easily provide a mock implementation of the ws using any of the standard custom provider techniques, including useClass, useValue, and useFactory.

    const module: TestingModule = await Test.createTestingModule({
      providers: [
        MyService,
        {
          provide: getWebSocketToken(),
          useValue: mockProvider,
        },
      ],
    }).compile();

    Change Log

    See Changelog for more information.

    Contributing

    Contributions welcome! See Contributing.

    Authors

    License

    Licensed under the Apache 2.0 - see the LICENSE file for details.

    Install

    npm i nestjs-websocket

    DownloadsWeekly Downloads

    119

    Version

    0.1.3

    License

    Apache

    Unpacked Size

    40.3 kB

    Total Files

    24

    Last publish

    Collaborators

    • jarcodallo
    • annriera