Skip to content

Commit

Permalink
feat: include features from Socket.IO v4
Browse files Browse the repository at this point in the history
The codebase is now written in TypeScript.

Additional features:

- https://socket.io/docs/v4/migrating-from-3-x-to-4-0/#Allow-excluding-specific-rooms-when-broadcasting
- https://socket.io/docs/v4/migrating-from-3-x-to-4-0/#Additional-utility-methods
- https://socket.io/docs/v4/migrating-from-3-x-to-4-0/#Typed-events

BREAKING CHANGE: the "redis" package is not installed by default
anymore, you'll now need to create your own redis client and pass it to
the Emitter constructor

Before:

```js
const io = require("socket.io-emitter")({ host: "127.0.0.1", port: 6379 });
```

After:

```js
const { Emitter } = require("socket.io-emitter");
const { createClient } = require("redis");

const redisClient = createClient();
const io = new Emitter(redisClient);
```

Related:

- #89
- #90
- #95
  • Loading branch information
darrachequesne committed Mar 17, 2021
1 parent ad920e4 commit a70db12
Show file tree
Hide file tree
Showing 12 changed files with 2,828 additions and 926 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
node_modules
dist/
.nyc_output/
184 changes: 112 additions & 72 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,130 +23,170 @@ It must be used in conjunction with [socket.io-redis](https://github.com/socketi
The current version is compatible with both:

- `socket.io-redis@5` (`socket.io@2`)
- `socket.io-redis@6` (`socket.io@3`)
- `socket.io-redis@6` (`socket.io@3` & `socket.io@4`)

## Table of content

- [How to use](#how-to-use)
- [Examples](#examples)
- [Error handling](#error-handling)
- [CommonJS](#commonjs)
- [TypeScript](#typescript)
- [Emit cheatsheet](#emit-cheatsheet)
- [API](#api)
- [Emitter(client[, opts])](#emitterclient-opts)
- [Emitter(clientUri[, opts])](#emitterclienturi-opts)
- [Emitter(opts)](#emitteropts)
- [Emitter#to(room:String):Emitter](#emittertoroomstringemitter)
- [Emitter#in(room:String):Emitter](#emitterinroomstringemitter)
- [Emitter#of(namespace:String):Emitter](#emitterofnamespacestringemitter)
- [Emitter#to(room)](#emittertoroomstringbroadcastoperator)
- [Emitter#in(room)](#emitterinroomstringbroadcastoperator)
- [Emitter#except(room)](#emitterexceptroomstringbroadcastoperator)
- [Emitter#of(namespace)](#emitterofnamespacestringemitter)
- [Emitter#socketsJoin()](#emittersocketsjoinroomsstringstring)
- [Emitter#socketsLeave()](#emittersocketsleaveroomsstringstring)
- [Emitter#disconnectSockets()](#emitterdisconnectsocketscloseboolean)
- [License](#license)

## How to use

### CommonJS

Installation: `npm i socket.io-emitter redis`

```js
const io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
const { Emitter } = require("socket.io-emitter");
const { createClient } = require("redis"); // not included, needs to be explicitly installed

const redisClient = createClient();
const io = new Emitter(redisClient);

setInterval(() => {
io.emit('time', new Date);
io.emit("time", new Date);
}, 5000);
```
```js
// Different constructor options.

//1. Initialize with host:port string
const io = require('socket.io-emitter')("localhost:6379")
// 2. Initlize with host, port object.
const io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
// 3. Can use other node_redis compatible client eg; ioredis.

const Redis = require("ioredis");
const redis = new Redis();
const io = require('socket.io-emitter')(redis);

// Make the emitter works with redis clustered environment.
const Cluster = new Redis.Cluster([
{
host: "localhost",
port: 6379
},
{
host: "localhost",
port: 6378
},
]);
const io = require('socket.io-emitter')(Cluster);

### TypeScript

Installation: `npm i socket.io-emitter redis @types/redis`

```ts
import { Emitter } from "socket.io-emitter";
import { createClient } from "redis";

const redisClient = createClient();
const io = new Emitter(redisClient);

setInterval(() => {
io.emit("time", new Date);
}, 5000);
```

With typed events:

```ts
import { Emitter } from ".";
import { createClient } from "redis";

interface Events {
basicEmit: (a: number, b: string, c: number[]) => void;
}

const redisClient = createClient();
const io = new Emitter<Events>(redisClient);

io.emit("basicEmit", 1, "2", [3]);
```

## Examples
## Emit cheatsheet

```js
const io = require('socket.io-emitter')({ host: '127.0.0.1', port: 6379 });
const { Emitter } = require("socket.io-emitter");
const { createClient } = require("redis"); // not included, needs to be explicitly installed

const redisClient = createClient();
const io = new Emitter(redisClient);

// sending to all clients
io.emit('broadcast', /* ... */);
io.emit(/* ... */);

// sending to all clients in 'game' room
io.to('game').emit('new-game', /* ... */);
// sending to all clients in 'room1' room
io.to("room1").emit(/* ... */);

// sending to all clients in 'room1' except those in 'room2'
io.to("room1").except("room2").emit(/* ... */);

// sending to individual socketid (private message)
io.to(socketId).emit('private', /* ... */);
io.to(socketId).emit(/* ... */);

const nsp = io.of('/admin');
const nsp = io.of("/admin");

// sending to all clients in 'admin' namespace
nsp.emit('namespace', /* ... */);
nsp.emit(/* ... */);

// sending to all clients in 'admin' namespace and in 'notifications' room
nsp.to('notifications').emit('namespace', /* ... */);
nsp.to("notifications").emit(/* ... */);
```

**Note:** acknowledgements are not supported

## Error handling

Access the `redis` to subscribe to its `error` event:

```js
const emitter = require('socket.io-emitter')("localhost:6379");

emitter.redis.on('error', (err) => {
console.log(err);
});
```

## API

### Emitter(client[, opts])

`client` is a [node_redis](https://github.com/mranney/node_redis)
compatible client that has been initialized with the `return_buffers`
option set to `true`. This argument is optional.
option set to `true`.

The following options are allowed:

- `key`: the name of the key to pub/sub events on as prefix (`socket.io`)
- `host`: host to connect to redis on (`localhost`)
- `port`: port to connect to redis on (`6379`)
- `socket`: unix domain socket to connect to redis on (`"/tmp/redis.sock"`)

### Emitter(clientUri[, opts])
### Emitter#to(room:String):BroadcastOperator
### Emitter#in(room:String):BroadcastOperator

Same as above, but `clientUri` is a string of the format `host:port`
to connect to redis to.
Specifies a specific `room` that you want to emit to.

### Emitter(opts)
### Emitter#except(room:String):BroadcastOperator

If you don't want to supply a redis client object, and want
`socket.io-emitter` to intiialize one for you, make sure to supply the
`host` and `port` options.
Specifies a specific `room` that you want to exclude from broadcasting.

### Emitter#to(room:String):Emitter
### Emitter#in(room:String):Emitter
### Emitter#of(namespace:String):Emitter

Specifies a specific `room` that you want to emit to.
Specifies a specific namespace that you want to emit to.

### Emitter#socketsJoin(rooms:String|String[])

### Emitter#of(namespace:String):Emitter
Makes the matching socket instances join the specified rooms:

Specifies a specific namespace that you want to emit to.
```js
// make all Socket instances join the "room1" room
io.socketsJoin("room1");

// make all Socket instances of the "admin" namespace in the "room1" room join the "room2" room
io.of("/admin").in("room1").socketsJoin("room2");
```

### Emitter#socketsLeave(rooms:String|String[])

Makes the matching socket instances leave the specified rooms:

```js
// make all Socket instances leave the "room1" room
io.socketsLeave("room1");

// make all Socket instances of the "admin" namespace in the "room1" room leave the "room2" room
io.of("/admin").in("room1").socketsLeave("room2");
```

### Emitter#disconnectSockets(close:boolean)

Makes the matching socket instances disconnect:

```js
// make all Socket instances disconnect
io.disconnectSockets();

// make all Socket instances of the "admin" namespace in the "room1" room disconnect
io.of("/admin").in("room1").disconnectSockets();

// this also works with a single socket ID
io.of("/admin").in(theSocketId).disconnectSockets();
```

## License

Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: '2.0'
services:
redis:
image: redis:5
ports:
- "6379:6379"
Loading

0 comments on commit a70db12

Please sign in to comment.