Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

spiral-modules/websocket-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spiral Framework WebSocket

JavaScript WebSockets client library with channel support.

Since RoadRunner 2.x, the communication protocol has been changed. Below is a table of version compatibility.

RoadRunner spiralscout/websockets
1.0+ 0.0.1+
2.3+ 0.1.0+

Installation

SFSocket available for installing with npm or yarn

    npm install @spiralscout/websockets -D  
    yarn add @spiralscout/websockets 

Next use it like so

    import { SFSocket } from '@spiralscout/websockets';

Or via bundle file

    <script src="/build/socket.js"></script>
    <script type="text/javascript">
        var Socket = SFSocket.SFSocket;
        var connection = new Socket({ host: 'localhost'});
    </script>

If you prefer CDN usage, use following URL for most recent version

https://cdn.jsdelivr.net/gh/spiral/websockets/build/socket.js

API

SFSocket proposes easy way to use WebSockets:

import { SFSocket } from '@spiralscout/websockets';

const socketOptions = { host: 'localhost' };

// create an instance of SFSocket
const ws = new SFSocket(socketOptions);

const prepareEvent = event => doSomething(event);

// subscribe to server
ws.subscribe('message', prepareEvent);

// runtime ready for all instances
SFSocket.ready();

// unsubscribe from server 
ws.unsubscribe('message', prepareEvent);

// disconnect from server 
ws.disconnect();

SFSocket

SFSocket
Properties
static instances SFSocket[]
Array of all existing sockets
static isReady boolean
false before ready() is called. If is true any new SFSocket will connect upon creation.
Methods
static ready() Marks sockets as ready and launches all connections.
Use if you need to make all sockets to connect automatically on creation
constructor(options: ISFSocketConfig) Create websocket connection
options: ISFSocketConfig - connection options
joinChannel(channel, dontJoin) Creates a named channel and joins it
channel: string name of channel to join. Should NOT be one of system ones: @join, #join, @leave, #leave
dontJoin: boolean default false if true, channel is created, registered inside instance but not joined automatically. Call join method to join later.
return value: Channel returns channel object
getChannel(channel) Gets a previously created named channel
return value: Channel returns channel object
leaveChannel(channel) Removes a named channel and leaves it
channel: string name of channel to join. Should NOT be one of system ones @join, #join, @leave, #leave
return value: Channel returns channel object
subscribe(event, callback, channel) Subscribes to specific event
event: string one of valid event codes. See table below for possible events and their payload
callback: (payload) => void callback to call. Type of payload depends on event type
channel: string (optional) Channel name to follow. If none, subscribes for all. Note that doesn't automatically join channel, just adds listener to existing one.
unsubscribe(event, callback, channel) Unsubscribes from specific event
event: string one of valid event codes. See table below for possible events and their payload
callback: (payload) => void callback to call. Type of payload depends on event type
channel: string (optional) Channel name to unfollow. If none, unsubscribes from all channels. Note that doesn't automatically remove channel, just removes listener from existing one.

SFSocket constructor options

SFSocket supports standard (ws) and secure (wss) protocols.

SFSocket constructor new SFSocket(options: ISFSocketConfig) is expecting options of type ISFSocketConfig

ISFSocketConfig
host string
Host websocket should connect to
port string or number
(optional) Port websocket should connect to
Default: 80 or 443 if useTSL = true
useTSL boolean
(optional) Use TSL wss instead of regular ws protocol
Default: false
path string
(optional) Server path part
Default: empty
queryParams object of {[key: string]: string} type
(optional) Query params map to append to path
Default: empty
unavailableTimeout number
(optional) A timeout which is considered to be large enough to stop retrying reconnects if server response takes longer
Default: 10000

For example to establish connection to ws://some.domain.com/foo?bar=1 use following code

import { SFSocket } from '@spiralscout/websockets';

const socketOptions = {
  host: 'some.domain.com',
  port: '80',
  path: 'foo',
  queryParams: { bar: '1' }
}

const ws = new SFSocket(socketOptions);

SFSocket channels

Channel
Properties
status string Channel status, can be closed, joinin, joined, leaving or error
name string Channel name
Methods
constructor(name: string, socket: SFSocket) Creates a channel based on specific SFSocket
name: string - channel name. Can NOT be @join, #join, @leave, #leave
join() Enables channel and sends join command once connection is working
leave() Disables channel and sends leave command if connection is working
subscribe(event, callback) Subscribes to specific event
event: string one of valid event codes. See table below for possible events and their payload
callback: (payload) => void callback to call. Type of payload depends on event type
unsubscribe(event, callback) Unsubscribes from specific event
event: string one of valid event codes. See table below for possible events and their payload
callback: (payload) => void callback to call. Type of payload depends on event type
connect() Starts connection. This method is automatically called after SFSocket.ready() for all existing and new instances
disconnect() Drops connection

Supported events

SFSocket and Channel make it possible to subscribe to connected, message, closed and error events

SFSocket additionally allows to subscribe to channel_joined, channel_join_failed and channel_left events

Events
message ISFSocketEvent
Generic event of message from specific channel or broadcasted Payload depends on channel server implementation
error ISFSocketEvent
Event of error happened in specific channel or broadcasted Payload would contain error details
closed ISFSocketEvent
Connection was closed due some error. Socket might automatically reconnect after that.
channel_joined string[]
Indicates server confirming joining specific channels
channel_left string[]
Indicates server confirming leaving specific channels
channel_join_failed string[]
Indicates server denies joining specific channels

ISFSocketEvent structure

ISFSocketEvent
type string
sfSocket:message, sfSocket:closed or sfSocket:error depending on event tracked.
data any
Any serializable payload depending on implementation that refers to successful flow
error string
Error message
context object
Object with event context details
context.code number
Error code if relevant
context.channel string
Channel name if relevant
Message Event
const MessageEvent: ISFSocketEvent = {
  context: {
    channel: 'channel', // optional
    code: 1001, // optional
  },
  data: 'message',
  error: null,
  type: 'sfSocket:message',
};
Error Event
const ErrorEvent: ISFSocketEvent = {
  context: {
    channel: 'channel', // optional
    code: 1006, // optional
  },
  data: null,
  error: 'message',
  type: 'sfSocket:error',
};

Samples

Working with events

const ws = new SFSocket(socketOptions);

ws.subscribe('connected', () => console.log('connected'));
ws.subscribe('error', (sfSocketEvent) => doSomething(sfSocketEvent));
ws.subscribe('message', (sfSocketEvent) => doSomething(sfSocketEvent));
ws.subscribe('closed', () => console.log('closed'));

const channel = ws.joinChannel('topic1');

channel.subscribe('connected', () => console.log('connected'));
channel.subscribe('error', (sfSocketEvent) => doSomething(sfSocketEvent));
channel.subscribe('message', (sfSocketEvent) => doSomething(sfSocketEvent));
channel.subscribe('closed', () => console.log('closed'));

Multiple channels creation

import { SFSocket } from '@spiralscout/websockets';

const socketOptions = { host: 'localhost' };

const ws = new SFSocket(socketOptions);

SFSocket.ready();

// create a channel and it is automatically connected to server
const channel1 = ws.joinChannel('channel_1');
const channel2 = ws.joinChannel('channel_2', true); // This one wont auto-join now

// subscribe the channel to server 
channel1.subscribe('message', (event) => doSomething(event));
channel2.subscribe('message', (event) => doSomething(event));

channel2.join(); // Start receiving messages for channel2 

// disconnect the channel from server 
channel1.leave();
channel2.leave();

// disconnect everything
ws.disconnect()

Custom commands

Sending custom commands is supported via sendCommand method. join and leave commands can NOT be used as command name, payload can be any serializable data.

const cmd = 'foo'; // Any string except 'join' or 'leave'
const data = ['bar']; // Serializable data
ws.sendCommand(cmd, data);

Development

Prerequisites
Windows

On windows execute git config core.autocrlf false to disable automatic line ending conversion.