WebSockets Server and Client API for Node.js and the browser, with rooms support.
The goal of this project is to provide a developer friendly API that just works™.
npm install angelia.io
// server.js (node.js)
import Server from 'angelia.io/server'
class FancyChat {
typing(socket, data, callback) {
console.log('Im', data ? ' typing' : ' not typing')
}
theMessage(socket, data, callback) {
console.log('the message is', data, socket)
socket.emit('gotIt', 'thanks')
callback('yes Im sure')
}
}
Server.on(FancyChat)
class myConnection {
connect(socket, request) {
console.log('socket connected', socket)
}
disconnect(socket, code, message) {
console.log('socket disconnected', code, message, socket)
}
}
Server.on(myConnection)
Server.listen()
// index.js (browser)
import Client from 'angelia.io/client'
const socket = new Client('ws://localhost:3001')
socket.emit('typing', true)
setTimeout(() => {
socket.emit('typing', false)
socket.emit('theMessage', 'hi there!', data => {
console.log('yep', data)
})
}, 5000)
socket.on('gotIt', message => {
console.log('Server got it', message)
})
name | kind | default | description |
---|---|---|---|
hostname |
String | undefined | the hostname if any |
port |
Number | 3001 | the port to use for this server |
maxMessageSize |
Number | 5 | max size in mb of a message received |
maxPostSize |
Number | 50 | max size in mb of a POST message |
skipUTF8Validation |
Boolean | false | allows to skip utf8 validation |
timeout |
Number | 60000 | time in milliseconds after a socket is considered gone, minimum value is 10000 |
The server
object can be accessed from everywhere
signature | kind | description |
---|---|---|
since |
Number | timestamp of initialization |
now |
Number | timestamp that updates every half a second |
port |
Number | port used by this server |
hostname |
String | the hostname if any |
maxMessageSize |
Number | maximum message size in mb |
maxPostSize |
Number | maximum POST size in mb |
timeout |
Number | after how long the socket is considered gone, in ms |
connections |
Number | count of sockets connected |
served |
Number | count of sockets ever connected |
bytesReceived |
Number | sum of bytes the server has ever received |
bytesSent |
Number | sum of bytes sent by the server |
messagesGarbage |
Number | count of messages without a listener |
messagesReceived |
Number | count of messages ever received |
messagesSent |
Number | count of messages ever sent |
messagesSentCacheHit |
Number | count of messages ever sent that were cached |
serverErrors |
Number | count of server errors |
socketErrors |
Number | count of socket errors |
events |
Object | ref to events, ex: server.events.typing() to dispatch typing to anyone listening to it |
on(Class) |
Function | attaches all methods of a Class as listeners |
emit(key, [value]) |
Function | emits to all connected sockets |
once(key, [value]) |
Function | emits to the sockets and replace if exists a pending message with the same key |
broadcast(sender, key, [value]) |
Function | emits to all connected sockets except sender |
broadcastOnce(sender, key, [value]) |
Function | emits to the sockets except sender and replace if exists a pending message with the same key |
sockets |
Set | a Set() with all the current connected sockets |
The socket
object is given to you by a listener
signature | kind | description |
---|---|---|
server |
Object | reference to the server |
ip |
String | ip of the socket |
userAgent |
String | user agent of the socket |
params |
Object | the params sent via the client constructor |
since |
Number | timestamp of first seen |
seen |
Number | timestamp of last received message |
ping |
Number | delay with the socket in milliseconds (full round trip) |
timedout |
Boolean | whether we lost connection with this socket |
bytesSent |
Number | sum of bytes sent to this socket |
bytesReceived |
Number | sum of bytes received from this socket |
messagesSent |
Number | count of messages sent to this socket |
messagesReceived |
Number | count of messages received from this socket |
rooms |
Set | a set with the rooms where this socket is in |
emit(key, [value]) |
Function | emits to client |
once(key, [value]) |
Function | replace if exists a pending message with the same key from emit queue |
disconnect([noReconnect]) |
Function | disconnects the socket from the server, pass true to prevent re-connections |
Listen to an event by creating a class with any name, and give to
methods the name of the things you want to listen to. Then add the
class to the listeners as Server.on(MyClass)
and you are done.
On user defined listeners, the listener receives three things as sent
by the client: socket
, data
and a callback
; Example:
class FancyChat { typing(socket, data, callback?) { console.log(socket, data) }}
.
There's a bunch of handy predefined events dispatched
signature | description |
---|---|
listen() |
when the server is about to listen |
connect(socket, request) |
when a socket connects |
disconnect(socket, code, message) |
when a socket gets disconnected |
ping(socket) |
when we got an update of the ping for a socket |
timeout(socket, delay) |
when we are about to disconnect a timedout socket, gives the delay in milliseconds |
garbage(socket, data) |
if the client sends a message that the server has no listener this will be dispatched |
incoming(socket, messages) |
for debugging: ref to array of incoming messages received before dispatching to listeners |
outgoing(socket, messages) |
for debugging: ref to array of outgoing messages before sending to socket |
Arguments for the constructor
const socket = new Client({
url: 'ws://localhost:3001',
params: function () {
return { fast: 'data', test: 'a space' }
},
noConnect: true,
})
socket.connect()
You may also do like this if you don't need any option
const socket = new Client('ws://localhost:3001')
The client API is similar to regular event handling
signature | kind | description |
---|---|---|
connected |
Boolean | true when the socket is connected else false |
connect() |
Function | connects to the server, it auto-connects on disconnection |
disconnect([noReconnect]) |
Function | disconnects from the server, pass true to prevent re-connections |
on(key, callback) |
Function | listens for an event, returns an off function to stop listening |
emit(key, [value, callback]) |
Function | emits data to the server |
As in socket.on('connect', () => console.log('connect happened!'))
signature | description |
---|---|
connect |
this happens only once when we connect to the server, any future connection is a reconnect |
reconnect |
if we were connected at least once, then any re-connection will dispatch this event instead of connect |
disconnect |
when we disconnect from the server |
- Create a room class that extends
Room
- Create a room list that will allow joining sockets
- Join a socket in a room, a socket may join multiple rooms. Rooms
are created when the
id
of the room doesn't exists, and deleted when there are no sockets in the room and the room doesn't have the flagpersistent
- A socket will leave automatically all rooms on disconnection
socket.rooms
is a set with all the rooms the socket joinedid
is assigned to the room on creation
import { Room, Rooms } from 'angelia.io/server'
class GameRoom extends Room {
persistent = false
onCreate(socket) {
console.log('creating room', this.id, socket)
}
onDelete(socket) {
console.log('deleting room', this.id, socket)
}
onJoin(socket) {
console.log('socket joined room', this.id, socket)
socket.game = this
this.emit('user joined', 'data here')
}
onLeave(socket) {
console.log('socket left room', this.id, socket)
socket.game = undefined
this.emit('user left', 'data here')
}
}
// games is a room list
const games = new Rooms(GameRoom)
class Connection {
connect(socket) {
games.join(socket, 'room id here')
socket.game.id === 'room id here'
console.log(socket.rooms)
games.leave(socket, 'room id here')
games.join(socket, 'a different room')
socket.game.id === 'a different room'
games.leave(socket, 'a different room')
}
}
Server.on(Connection)
Server.listen()
Iterating returns the rooms
signature | kind | description |
---|---|---|
get(id) |
method | gets room with such an id |
join(socket, [id]) |
method | adds socket to room id |
leave(socket, [id]) |
method | removes socket from room id |
connections |
number | number of sockets in this room list |
sockets |
Iterator | sockets in this room list |
emit(key, [value]) |
method | emits to all sockets in this room list |
once(key, [value]) |
method | emits once to all sockets in this room list |
broadcast(socket, key, [value]) |
method | emits to other sockets in this room list |
broadcastOnce(socket, key, [value]) |
method | emits once to other sockets in this room list |
map(fn) |
method | returns mapped array |
filter(fn) |
method | returns mapped filtered array |
- Create a room instance that extends
Room
- Join a socket in a room, a socket may join multiple rooms.
- A socket will leave automatically all rooms on disconnection
socket.rooms
is a set with all the rooms the socket joined- Keep in mind that
onCreate
andonDelete
are not dispatched when the room is manged by yourself. The construtor could be used for simulatingonCreate
andonDelete
only you will know when to dispose such a variable.
import { Room } from 'angelia.io/server'
class Lobby extends Room {
persistent = true
id = 'lobby'
onJoin(socket) {
console.log('socket joined room', this.id, socket)
}
}
// lobby is just 1 room
const lobby = new Lobby()
class Connection {
connect(socket) {
lobby.join(socket)
lobby.leave(socket)
}
}
Server.on(Connection)
Server.listen()
Iterating returns the sockets
signature | kind | description |
---|---|---|
onCreate(socket) |
method | dispatched when the room is created |
onDelete(socket) |
method | dispatched when the room is deleted |
onJoin(socket) |
method | dispatched when a socket joins the room |
onLeave(socket) |
method | dispatched when a socket leaves the room |
persistent |
boolean | to not delete rooms when there are no sockets in |
connections |
number | number of sockets in the room |
sockets |
Set | sockets in the room |
emit(key, [value]) |
method | emits to all sockets in the room |
once(key, [value]) |
method | emits once to all sockets in the room |
broadcast(socket, key, [value]) |
method | emits to other sockets in the room |
broadcastOnce(socket, key, [value]) |
method | emits once to other sockets in the room |
id |
any | the room id |
join(socket) |
method | adds a socket to the room |
leave(socket) |
method | remves a socket from the room |
Like Set
but with two aditional methods
signature | kind | description |
---|---|---|
map(fn) |
method | returns mapped array |
filter(fn) |
method | returns mapped filtered array |
- Tito Bouzout https://github.com/titoBouzout
- Anthony K. https://github.com/boredofnames