Skip to content

Commit 586eaec

Browse files
authored
Merge pull request #2 from blockcoders/feature/update-readme
Feature/update readme
2 parents bbfef69 + 74c3e9d commit 586eaec

22 files changed

+1180
-878
lines changed

.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
2+
"printWidth": 120,
23
"singleQuote": true,
4+
"semi": false,
5+
"bracketSpacing": true,
36
"trailingComma": "all"
47
}

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Changelog
22

33
## 0.1.0
4-
Published by **[jarcodallo](https://github.com/jarcodallo)** on **pending**
4+
Published by **[jarcodallo](https://github.com/jarcodallo)** on **2021/09/17**
5+
- [#2](https://github.com/blockcoders/nestjs-websocket/pull/2) Update README.md and linter config
6+
- [#d13d2db](https://github.com/blockcoders/nestjs-websocket/commit/d13d2db7287ae9784b64940a2fdcb07d39975b03) Update README.md
7+
- [#a9a54ca](https://github.com/blockcoders/nestjs-websocket/commit/a9a54ca0796d466e35adcbb96e8a90412063402f) Websocket client for nest

README.md

Lines changed: 230 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/nestjs-websocket)](https://snyk.io/test/github/blockcoders/nestjs-websocket)
77
[![supported platforms](https://img.shields.io/badge/platforms-Express%20%26%20Fastify-green)](https://img.shields.io/badge/platforms-Express%20%26%20Fastify-green)
88

9-
Websocket utility for NestJS based on [WS](https://www.npmjs.com/package/ws)
9+
Websocket Client for NestJS based on [ws](https://www.npmjs.com/package/ws)
1010

1111
## Install
1212

@@ -18,17 +18,35 @@ npm i nestjs-websocket
1818

1919
### Configuration params
2020

21-
The url param that websocket module expects should be a string, for example:
21+
`nestjs-websocket` can be configured with this options:
2222

2323
```ts
24-
{
25-
url: 'ws://localhost:3000',
24+
/**
25+
* WebSocket Client options
26+
* @see {@link https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocket}
27+
*/
28+
interface WebSocketModuleOptions {
29+
/**
30+
* Required parameter a URL to connect to.
31+
* such as http://localhost:3000 or wss://localhost:3000.
32+
*/
33+
url: string | URL;
34+
35+
/**
36+
* Optional parameter a list of subprotocols.
37+
*/
38+
protocols?: string | string[]
39+
40+
/**
41+
* Optional parameter a client or http request options.
42+
*/
43+
options?: ClientOptions | ClientRequestArgs
2644
}
2745
```
2846

2947
### Synchronous configuration
3048

31-
Use `WebSocketModule.forRoot` method with [String param](#configuration-params):
49+
Use `WebSocketModule.forRoot` method with [Options interface](#configuration-params):
3250

3351
```ts
3452
import { WebSocketModule } from 'nestjs-websocket'
@@ -37,6 +55,17 @@ import { WebSocketModule } from 'nestjs-websocket'
3755
imports: [
3856
WebSocketModule.forRoot({
3957
url: 'ws://localhost:3000',
58+
protocols: ['foo', 'bar'],
59+
options: {
60+
followRedirects: false,
61+
handshakeTimeout: 10000,
62+
maxPayload: 2000000,
63+
maxRedirects: 10,
64+
origin: 'http:/example.com',
65+
perMessageDeflate: false,
66+
protocolVersion: 1,
67+
skipUTF8Validation: false,
68+
},
4069
}),
4170
],
4271
...
@@ -46,22 +75,35 @@ class MyModule {}
4675

4776
### Asynchronous configuration
4877

49-
`WebSocketModule.forRootAsync` allows you, for example, inject `ConfigService` to use it in Nest `useFactory` method.
78+
With `WebSocketModule.forRootAsync` you can, for example, import your `ConfigModule` and inject `ConfigService` to use it in `useFactory` method.
79+
80+
`useFactory` should return object with [Options interface](#configuration-params)
5081

51-
`useFactory` should return an object with [String param](#configuration-params).
82+
Here's an example:
5283

5384
```ts
85+
import { Module, Injectable } from '@nestjs/common'
5486
import { WebSocketModule } from 'nestjs-websocket'
5587

5688
@Injectable()
89+
class ConfigService {
90+
public readonly url = 'ws://localhost:3000'
91+
}
92+
93+
@Module({
94+
providers: [ConfigService],
95+
exports: [ConfigService]
96+
})
97+
class ConfigModule {}
98+
5799
@Module({
58100
imports: [
59101
WebSocketModule.forRootAsync({
60102
imports: [ConfigModule],
61103
inject: [ConfigService],
62104
useFactory: (config: ConfigService) => {
63105
return {
64-
url: 'ws://localhost:3000'
106+
url: config.url,
65107
}
66108
},
67109
}),
@@ -71,10 +113,189 @@ import { WebSocketModule } from 'nestjs-websocket'
71113
class MyModule {}
72114
```
73115

116+
Or you can just pass `ConfigService` to `providers`, if you don't have any `ConfigModule`:
117+
118+
```ts
119+
import { Module, Injectable } from '@nestjs/common'
120+
import { WebSocketModule } from 'nestjs-websocket'
121+
122+
@Injectable()
123+
class ConfigService {
124+
public readonly url = 'ws://localhost:3000'
125+
}
126+
127+
@Module({
128+
imports: [
129+
WebSocketModule.forRootAsync({
130+
providers: [ConfigService],
131+
inject: [ConfigService],
132+
useFactory: (config: ConfigService) => {
133+
return {
134+
url: config.url,
135+
}
136+
},
137+
}),
138+
],
139+
controllers: [TestController]
140+
})
141+
class TestModule {}
142+
```
143+
144+
## WebSocketClient
145+
146+
`WebSocketClient` implements a [WebSocket](https://github.com/websockets/ws/blob/master/doc/ws.md#class-websocket). So if you are familiar with it, you are ready to go.
147+
148+
```ts
149+
import { Injectable } from '@nestjs/common'
150+
import {
151+
InjectWebSocketProvider,
152+
WebSocketClient,
153+
OnOpen,
154+
OnMessage,
155+
} from 'nestjs-websocket';
156+
157+
@Injectable()
158+
class TestService {
159+
private data: Record<any, any> = {}
160+
161+
constructor(
162+
@InjectWebSocketProvider()
163+
private readonly ws: WebSocketClient,
164+
) {}
165+
166+
@OnOpen()
167+
onOpen() {
168+
this.ws.send(JSON.stringify(eventData))
169+
}
170+
171+
@OnMessage()
172+
message(data: WebSocketClient.Data) {
173+
this.data = JSON.parse(data.toString())
174+
}
175+
176+
async getData(): Promise<Record<any, any>> {
177+
return this.data
178+
}
179+
}
180+
```
181+
182+
## Websocket Events
183+
184+
### EventListener
185+
186+
`@EventListener` decorator will handle any event emitted from websocket server.
187+
188+
```ts
189+
import { Injectable } from '@nestjs/common'
190+
import { ClientRequest, IncomingMessage } from 'http'
191+
import {
192+
EventListener
193+
} from 'nestjs-websocket';
194+
195+
@Injectable()
196+
class TestService {
197+
@EventListener('open')
198+
open() {
199+
console.log('The connection is established.')
200+
}
201+
202+
@EventListener('ping')
203+
ping(data: Buffer) {
204+
console.log(`A ping ${data.toString()} is received from the server.`)
205+
}
206+
207+
@EventListener('unexpected-response')
208+
unexpectedResponse(request: ClientRequest, response: IncomingMessage) {
209+
console.log(`The server response ${response} is not the expected one.`)
210+
}
211+
212+
@EventListener('upgrade')
213+
upgrade(response: IncomingMessage) {
214+
console.log(`Response headers ${response} are received from the server as part of the handshake.`)
215+
}
216+
}
217+
```
218+
219+
### OnOpen
220+
221+
`@OnOpen` is a shortcut for `@EventListener('open')`. Event emitted when the connection is established.
222+
223+
```ts
224+
import { Injectable } from '@nestjs/common'
225+
import {
226+
OnOpen
227+
} from 'nestjs-websocket';
228+
229+
@Injectable()
230+
class TestService {
231+
@OnOpen()
232+
open() {
233+
console.log('The connection is established.')
234+
}
235+
}
236+
```
237+
238+
### OnClose
239+
240+
`@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.
241+
242+
```ts
243+
import { Injectable } from '@nestjs/common'
244+
import {
245+
OnClose
246+
} from 'nestjs-websocket';
247+
248+
@Injectable()
249+
class TestService {
250+
@OnClose()
251+
close(code: number, reason: string) {
252+
console.log(`The connection is closed. Reason: ${code} - ${reason}`)
253+
}
254+
}
255+
```
256+
257+
### OnError
258+
259+
`@OnError` is a shortcut for `@EventListener('error')`. Event emitted when an error occurs. Errors may have a [.code](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#ws-error-codes) property.
260+
261+
```ts
262+
import { Injectable } from '@nestjs/common'
263+
import {
264+
OnError
265+
} from 'nestjs-websocket';
266+
267+
@Injectable()
268+
class TestService {
269+
@OnError()
270+
error(err: Error) {
271+
console.log(`An error occurs: ${err}`)
272+
}
273+
}
274+
```
275+
276+
### OnMessage
277+
278+
`@OnMessage` is a shortcut for `@EventListener('message')`. Event emitted when a message is received. `data` is the message content.
279+
280+
```ts
281+
import { Injectable } from '@nestjs/common'
282+
import {
283+
OnMessage
284+
} from 'nestjs-websocket';
285+
286+
@Injectable()
287+
class TestService {
288+
@OnMessage()
289+
message(data: WebSocketClient.Data) {
290+
console.log(`Data received: ${JSON.parse(data.toString())}`)
291+
}
292+
}
293+
```
294+
74295
## Testing a class that uses @InjectWebSocketProvider
75296

76297
This package exposes a `getWebSocketToken()` function that returns a prepared injection token based on the provided context.
77-
Using this token, you can easily provide a mock implementation of the [WS](https://github.com/websockets/ws) using any of the standard custom provider techniques, including useClass, useValue, and useFactory.
298+
Using this token, you can easily provide a mock implementation of the [ws](https://github.com/websockets/ws) using any of the standard custom provider techniques, including useClass, useValue, and useFactory.
78299

79300
```ts
80301
const module: TestingModule = await Test.createTestingModule({

__tests__/utils/app.gateway.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
import {
2-
MessageBody,
3-
SubscribeMessage,
4-
WebSocketGateway,
5-
} from '@nestjs/websockets';
1+
import { MessageBody, SubscribeMessage, WebSocketGateway } from '@nestjs/websockets'
62

73
@WebSocketGateway()
84
export class ApplicationGateway {
@@ -11,6 +7,6 @@ export class ApplicationGateway {
117
return {
128
event: 'pop',
139
data,
14-
};
10+
}
1511
}
1612
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Test } from '@nestjs/testing';
2-
import { WsAdapter } from '@nestjs/platform-ws';
3-
import { INestApplication } from '@nestjs/common';
4-
import { ApplicationGateway } from './app.gateway';
1+
import { Test } from '@nestjs/testing'
2+
import { WsAdapter } from '@nestjs/platform-ws'
3+
import { INestApplication } from '@nestjs/common'
4+
import { ApplicationGateway } from './app.gateway'
55

66
export async function createGatewayApp(): Promise<INestApplication> {
77
const testingModule = await Test.createTestingModule({
88
providers: [ApplicationGateway],
9-
}).compile();
10-
const app = await testingModule.createNestApplication();
9+
}).compile()
10+
const app = await testingModule.createNestApplication()
1111

12-
app.useWebSocketAdapter(new WsAdapter(app));
12+
app.useWebSocketAdapter(new WsAdapter(app))
1313

14-
return app;
14+
return app
1515
}

__tests__/utils/extraWait.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { Adapter } from './platforms';
2-
import { INestApplication } from '@nestjs/common';
3-
import { FastifyAdapter } from '@nestjs/platform-fastify';
1+
import { Adapter } from './platforms'
2+
import { INestApplication } from '@nestjs/common'
3+
import { FastifyAdapter } from '@nestjs/platform-fastify'
44

55
export async function extraWait(adapter: Adapter, app: INestApplication) {
66
if (adapter === FastifyAdapter) {
7-
const instance = app.getHttpAdapter().getInstance();
7+
const instance = app.getHttpAdapter().getInstance()
88
if (instance && typeof instance.ready === 'function') {
9-
await instance.ready();
9+
await instance.ready()
1010
}
1111
}
1212
}

__tests__/utils/platforms.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { AbstractHttpAdapter } from '@nestjs/core';
2-
import { Type } from '@nestjs/common';
3-
import { FastifyAdapter } from '@nestjs/platform-fastify';
4-
import { ExpressAdapter } from '@nestjs/platform-express';
1+
import { AbstractHttpAdapter } from '@nestjs/core'
2+
import { Type } from '@nestjs/common'
3+
import { FastifyAdapter } from '@nestjs/platform-fastify'
4+
import { ExpressAdapter } from '@nestjs/platform-express'
55

6-
export type Adapter = Type<AbstractHttpAdapter<any, any, any>>;
6+
export type Adapter = Type<AbstractHttpAdapter<any, any, any>>
77

8-
export const platforms: Adapter[] = [ExpressAdapter, FastifyAdapter];
8+
export const platforms: Adapter[] = [ExpressAdapter, FastifyAdapter]

__tests__/utils/randomPort.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
export function randomPort(min = 5000, max = 7000): number {
2-
return parseInt((Math.random() * (max - min) + min).toFixed());
2+
return parseInt((Math.random() * (max - min) + min).toFixed())
33
}

0 commit comments

Comments
 (0)