Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/titobouzout/angelia.io
WebSockets Server and Client for node.js and the browser
https://github.com/titobouzout/angelia.io
angelia socket sockets websocket-client websocket-server websockets
Last synced: 10 days ago
JSON representation
WebSockets Server and Client for node.js and the browser
- Host: GitHub
- URL: https://github.com/titobouzout/angelia.io
- Owner: titoBouzout
- Created: 2021-02-12T06:41:21.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-11-27T00:24:31.000Z (about 2 months ago)
- Last Synced: 2025-01-04T20:52:10.992Z (16 days ago)
- Topics: angelia, socket, sockets, websocket-client, websocket-server, websockets
- Language: JavaScript
- Homepage: https://github.com/titoBouzout/angelia.io
- Size: 204 KB
- Stars: 3
- Watchers: 4
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: readme.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
# angelia.io
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™.## Installation
`npm install angelia.io`
## Example
```js
// 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)
})
```## Server Documentation (Node.js)
### `Server.listen` Options
| 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 |### `Server` Object
The `server` object can be accessed from everywhere
#### List of `Server` Object Properties
| 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 |### `Socket` Object
The `socket` object is given to you by a listener
#### List of `Socket` Object Properties
| 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 |### Server Listeners
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) }}`.#### List of Predefined `Server` Events
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 |## Client API (Browser)
### `Client` Options
Arguments for the constructor
```js
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
```js
const socket = new Client('ws://localhost:3001')
```### `Client` API
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 |#### List of Predefined `Client` Events
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 |## Rooms
### Via a `Rooms` list
1. Create a room class that extends `Room`
2. Create a room list that will allow joining sockets
3. 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
flag `persistent`
4. A socket will leave automatically all rooms on disconnection
5. `socket.rooms` is a set with all the rooms the socket joined
6. `id` is assigned to the room on creation```js
import { Room, Rooms } from 'angelia.io/server'class GameRoom extends Room {
persistent = falseonCreate(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()
```#### `Rooms` Class
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 |### Via a `Room`
1. Create a room instance that extends `Room`
2. Join a socket in a room, a socket may join multiple rooms.
3. A socket will leave automatically all rooms on disconnection
4. `socket.rooms` is a set with all the rooms the socket joined
5. Keep in mind that `onCreate` and `onDelete` are not dispatched when
the room is manged by yourself. The construtor could be used for
simulating `onCreate` and `onDelete` only you will know when to
dispose such a variable.```js
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()
```#### `Room` Class
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 |### `sockets` Object in `Room` and `Rooms`
Like `Set` but with two aditional methods
| signature | kind | description |
| ------------ | ------ | ----------------------------- |
| `map(fn)` | method | returns mapped array |
| `filter(fn)` | method | returns mapped filtered array |## Authors
- Tito Bouzout https://github.com/titoBouzout
- Anthony K. https://github.com/boredofnames## URLs
- https://github.com/titoBouzout/angelia.io
- https://www.npmjs.com/package/angelia.io