Skip to content

blockcoders/nestjs-websocket

Repository files navigation

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.

Packages

 
 
 

Contributors