npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jsonbird-websocket

v1.0.0

Published

JSONBird-WebSocket makes it easy to establish a JSON-RPC 2.0 client connection over WebSocket so that you can send and receive Remote Procedure Calls. It works in node.js and web browsers. If the connection closes or is unresponsive, an automatic reconnec

Downloads

18

Readme

JSONBird-WebSocket

Build Status Coverage Status Greenkeeper badge

JSONBird-WebSocket makes it easy to establish a JSON-RPC 2.0 client connection over WebSocket so that you can send and receive Remote Procedure Calls. It works in node.js and web browsers. If the connection closes or is unresponsive, an automatic reconnection will occur after a delay. This delay will slowly increase to avoid spamming the server.

This library uses the JSONBird module, which is a more generic JSON-RPC 2.0 library, which can be used to create any kind of client or server over different transports.

Almost all behaviour is configurable, examples include:

  • Passing different options to the ws module, such as TLS options and HTTP headers
  • Stopping automatic reconnects based on the close code received from the server
  • Specifying a timeout per RPC call
  • Specifying a connection timeout
  • Specifying a different reconnect delay strategy (the default implementation includes exponential backoff and jitter)
  • Custom ping interval, method name, timeout and after how many failed pings the connection will be closed and reopened
  • Custom outgoing close codes for timeouts and internal errors
  • Performing RPC method calls from client to server, server to client, or bidirectional

However the default options should be good enough in most situations.

And some events are available that can be used to hook up logging or provide additional behaviour:

  • Connecting, opening and closing of the WebSocket connection
  • JSON-RPC 2.0 protocol errors
  • Ping failure & success

Support for HTML WebSocket in web browsers is provided thanks to the isomorphic-ws module. You can use browserify or webpack to generate a javascript bundle containing this library and the rest of your own code.

Installation

npm install --save jsonbird-websocket ws

The ws package does not have to be installed if you are only going to use this library for web browsers.

Pings

This library sends out ping messages as JSON-RPC method calls (NOT WebSocket pings), the other end is expected to reply to this method call as soon as possible (however the return value is ignored). The default name of this method is "jsonbird.ping".

This is an example of the message which will be sent out over the WebSocket connection periodically:

{"jsonrpc":"2.0","id":"10350 HJRolp3jG","method":"jsonbird.ping","params":[]}

The server is then expected to reply with:

{"jsonrpc":"2.0","id":"10350 HJRolp3jG","result":true}

These ping messages are used to ensure that the connection is healthy. If the server does not reply to pings the connection will eventually be closed (and then a new connection will be made).

Examples

const {WebSocketClient} = require('jsonbird-websocket');

async function example() {
  const rpc = new WebSocketClient({
    url: `ws://127.0.0.1:1234/`,
  });
  rpc.defaultTimeout = 5000;
  rpc.on('webSocketError', ({error}) => console.error('Connection failed', error));
  rpc.on('webSocketClose', ({code, reason}) => {
    console.log('Connection has been closed', code, reason);
    if (code === 1008) {
      // stop reconnecting when we receive this specific
      // close code from the server
      rpc.stop();
    }
  });

  // no connection will be made until .start()
  rpc.start();

  // Send an JSON-RPC 2.0 method call to the server:
  const result = await rpc.call('foo', 123, 456);
  console.log('result', result);

  // Start listening for method calls sent from the server to our client:
  rpc.method('sum', async (a, b) => a + b);
};

example().catch(console.error);

API Documentation

WebSocketClient

Kind: global class

new WebSocketClient([opts])

| Param | Type | Default | Description | | --- | --- | --- | --- | | [opts] | object | | The effect of these options are documented at the getter/setter with the same name | | opts.url | string | | | | [opts.createConnectionCallback] | function | ({WebSocket, url}) => new (require('isomorphic-ws'))(url) | | | [opts.reconnect] | boolean | true | | | [opts.reconnectDelayCallback] | function | x => 2**x * 100 * (Math.random() + 0.5) | | | [opts.reconnectCounterMax] | number | 8 | | | [opts.connectTimeout] | number | 10000 | | | [opts.consecutivePingFailClose] | number | 4 | | | [opts.timeoutCloseCode] | number | 4100 | | | [opts.internalErrorCloseCode] | number | 4101 | | | [opts.jsonbird] | object | | Options passed to the JSONBird constructor | | [opts.jsonbird.receiveErrorStack] | boolean | false | | | [opts.jsonbird.sendErrorStack] | boolean | false | | | [opts.jsonbird.firstRequestId] | number | 0 | The first request id to use | | [opts.jsonbird.sessionId] | string | "randomString()" | | | [opts.jsonbird.endOfJSONWhitespace=] | string | | | | [opts.jsonbird.endOnFinish] | boolean | true | | | [opts.jsonbird.finishOnEnd] | boolean | true | | | [opts.jsonbird.pingReceive] | boolean | true | | | [opts.jsonbird.pingMethod] | string | "'jsonbird.ping'" | | | [opts.jsonbird.pingInterval] | number | 2000 | | | [opts.jsonbird.pingTimeout] | number | 1000 | | | [opts.jsonbird.pingNow] | number | Date.now | Timer function used to figure out ping delays | | [opts.jsonbird.setTimeout] | function | global.setTimeout | | | [opts.jsonbird.clearTimeout] | function | global.clearTimeout | |

webSocketClient.url

The URL to which to connect; this should be the URL to which the WebSocket server will respond.

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | string |

webSocketClient.url ⇒ string

The URL to which to connect; this should be the URL to which the WebSocket server will respond.

Kind: instance property of WebSocketClient

webSocketClient.reconnect

If true, a new connection will be made (after a delay) if the connection closes for any reason (error, timeouts, explicit close)

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | boolean |

webSocketClient.reconnect ⇒ boolean

If true, a new connection will be made (after a delay) if the connection closes for any reason (error, timeouts, explicit close)

Kind: instance property of WebSocketClient

webSocketClient.consecutivePingFailClose

If this amount of pings fail consecutively, the connection will be automatically closed. If reconnect is true a new connection will be established.

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | number |

webSocketClient.consecutivePingFailClose ⇒ number

If this amount of pings fail consecutively, the connection will be automatically closed. If reconnect is true a new connection will be established.

Kind: instance property of WebSocketClient

webSocketClient.connectTimeout

Abort the connection if it takes longer than this many milliseconds to complete the connection attempt. This is the maximum amount of time that we will wait for the WebSocket readyState to transition from CONNECTING to OPEN

Kind: instance property of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | value | number | milliseconds |

webSocketClient.connectTimeout ⇒ number

Abort the connection if it takes longer than this many milliseconds to complete the connection attempt. This is the maximum amount of time that we will wait for the WebSocket readyState to transition from CONNECTING to OPEN

Kind: instance property of WebSocketClient
Returns: number - milliseconds

webSocketClient.timeoutCloseCode

The close code to send to the server when the connection is going to be closed because of a timeout

Kind: instance property of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | value | number | 1000 or in the range 3000 and 4999 inclusive |

webSocketClient.timeoutCloseCode ⇒ number

The close code to send to the server when the connection is going to be closed because of a timeout

Kind: instance property of WebSocketClient
Returns: number - 1000 or integer in the range 3000 and 4999 inclusive

webSocketClient.internalErrorCloseCode

The close code to send to the server when the connection is going to be closed because an error event was raised by the node.js stream api or jsonbird.

Kind: instance property of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | value | number | 1000 or in the range 3000 and 4999 inclusive |

webSocketClient.internalErrorCloseCode ⇒ number

The close code to send to the server when the connection is going to be closed because an error event was raised by the node.js stream api or jsonbird.

Kind: instance property of WebSocketClient
Returns: number - 1000 or in the range 3000 and 4999 inclusive

webSocketClient.createConnectionCallback

A callback which is called whenever this library wants to establish a new WebSocket connection. The callback is called with a single argument, an object containing the following properties:

  • "url" - The same value as this.url
  • "WebSocket" - The WebSocket class provided by the NPM package "isomorphic-ws"... If this library is used with browserify/webpack this will be equal to window.WebSocket. Otherwise this value will be equal to the NPM "ws" package.

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | function |

webSocketClient.createConnectionCallback ⇒ function

A callback which is called whenever this library wants to establish a new WebSocket connection. The callback is called with a single argument, an object containing the following properties:

  • "url" - The same value as this.url
  • "WebSocket" - The WebSocket class provided by the NPM package "isomorphic-ws"... If this library is used with browserify/webpack this will be equal to window.WebSocket. Otherwise this value will be equal to the NPM "ws" package.

Kind: instance property of WebSocketClient

webSocketClient.reconnectDelayCallback

A callback which is called after a failed connection to determine the delay before the next connection attempt. The callback is called with a single argument, a number specifying the current reconnectCounter. This counter is increased by 1 whenever a connection attempt fails, and it is slowly decreased while the connection is healthy

The reconnectCounter is always a value between 0 and this.reconnectCounterMax inclusive. The callback must return the reconnect delay as a number in milliseconds.

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | function |

webSocketClient.reconnectDelayCallback ⇒ function

A callback which is called after a failed connection to determine the delay before the next connection attempt. The callback is called with a single argument, a number specifying the current reconnectCounter. This counter is increased by 1 whenever a connection attempt fails, and it is slowly decreased while the connection is healthy

The reconnectCounter is always a value between 0 and this.reconnectCounterMax inclusive. The callback must return the reconnect delay as a number in milliseconds.

Kind: instance property of WebSocketClient

webSocketClient.reconnectCounterMax

The maximum value for the reconnectCounter (see reconnectDelayCallback). This can be used to easily set a maximum reconnect delay. For example if reconnectCounterMax is set to 8, and reconnectDelayCallback is set to the default value, the highest reconnect delay is: 2**8 * 100 * (Math.random() + 0.5) = random between 12800 and 38400

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | number |

webSocketClient.reconnectCounterMax ⇒ number

The maximum value for the reconnectCounter (see reconnectDelayCallback). This can be used to easily set a maximum reconnect delay. For example if reconnectCounterMax is set to 8, and reconnectDelayCallback is set to the default value, the highest reconnect delay is: 2**8 * 100 * (Math.random() + 0.5) = random between 12800 and 38400

Kind: instance property of WebSocketClient

webSocketClient.receiveErrorStack ⇒ boolean

If true and a remote method throws, attempt to read stack trace information from the JSON-RPC error.data property. This stack trace information is then used to set the fileName, lineNumber, columnNumber and stack properties of our local Error object (the Error object that the .call() function will reject with).

Kind: instance property of WebSocketClient

webSocketClient.receiveErrorStack

If true and a remote method throws, attempt to read stack trace information from the JSON-RPC error.data property. This stack trace information is then used to set the fileName, lineNumber, columnNumber and stack properties of our local Error object (the Error object that the .call() function will reject with).

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | boolean |

webSocketClient.sendErrorStack ⇒ boolean

If true, the fileName, lineNumber, columnNumber and stack of an Error thrown during a method is sent to the client using the JSON-RPC error.data property.

Kind: instance property of WebSocketClient

webSocketClient.sendErrorStack

If true, the fileName, lineNumber, columnNumber and stack of an Error thrown during a method is sent to the client using the JSON-RPC error.data property.

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | boolean |

webSocketClient.defaultTimeout ⇒ number

The timeout to use for an outgoing method call unless a different timeout was explicitly specified to call().

Kind: instance property of WebSocketClient

webSocketClient.defaultTimeout

The timeout to use for an outgoing method call unless a different timeout was explicitly specified to call().

Kind: instance property of WebSocketClient

| Param | Type | | --- | --- | | value | number |

webSocketClient.pingInterval ⇒ number

The time (in milliseconds) between each ping if isSendingPings is true. This time is in addition to the time spent waiting for the previous ping to settle.

Kind: instance property of WebSocketClient
Returns: number - milliseconds

webSocketClient.pingInterval

The time (in milliseconds) between each ping if isSendingPings is true. This time is in addition to the time spent waiting for the previous ping to settle.

Kind: instance property of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | value | number | milliseconds |

webSocketClient.pingTimeout ⇒ number

The maximum amount of time (in milliseconds) to wait for a ping method call to resolve.

Kind: instance property of WebSocketClient
Returns: number - milliseconds

webSocketClient.pingTimeout

The maximum amount of time (in milliseconds) to wait for a ping method call to resolve.

Kind: instance property of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | value | number | milliseconds |

webSocketClient.started ⇒ boolean

Returns true if this instance has been started. Which means that we are either setting up a connection, connected or waiting for a reconnect.

Kind: instance property of WebSocketClient

webSocketClient.hasActiveConnection ⇒ boolean

Returns true if there is an active WebSocket connection, in which case all RPC calls will be flushed out immediately and at which point we might receive RPC calls directed to us. If this property returns false, all outgoing RPC calls will be queued until we have a connection again

Kind: instance property of WebSocketClient

webSocketClient.method(name, func)

Registers a new method with the given name.

If the same method name is registered multiple times, earlier definitions will be overridden

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | name | string | The method name | | func | function | |

webSocketClient.methods(objectOrMap)

Registers multiple methods using an object or Map.

Each key->value pair is registered as a method. Values that are not a function are ignored. The this object during a method call is set to the objectOrMap (unless a Map was used)

If the same method name is registered multiple times, earlier definitions will be overridden

Kind: instance method of WebSocketClient

| Param | Type | | --- | --- | | objectOrMap | Object | Map |

webSocketClient.notification(name, func)

Registers a notification with the given name.

A notification is a method for which the return value or thrown Error is ignored. A response object is never sent.

If the same method name is registered multiple times, all functions handlers will be called (in the same order as they were registered)

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | name | string | The method name | | func | function | |

webSocketClient.notifications(objectOrMap)

Registers multiple notifications using an object or Map.

A notification is a method for which the return value or thrown Error is ignored. A response object is never sent.

If the same method name is registered multiple times, all functions handlers will be called (in the same order as they were registered)

Each key->value pair is registered as a notification. Values that are not a "function" are ignored. The this object during a method call is set to the objectOrMap (unless a Map was used)

If the same method name is registered multiple times, earlier definitions will be overridden

Kind: instance method of WebSocketClient

| Param | Type | | --- | --- | | objectOrMap | Object | Map |

webSocketClient.call(nameOrOptions, ...args) ⇒ Promise

Call a method on the remote instance, by sending a JSON-RPC request object to our write stream.

If no write stream has been set, the method call will be buffered until a write stream is set (setWriteStream). Note: if a read stream is never set, any call() will also never resolve.

Kind: instance method of WebSocketClient
Returns: Promise - A Promise which will resole with the return value of the remote method

| Param | Type | Description | | --- | --- | --- | | nameOrOptions | string | Object | The method name or an options object | | nameOrOptions.name | string | The method name | | nameOrOptions.timeout | number | A maximum time (in milliseconds) to wait for a response. The returned promise will reject after this time. | | ...args | * | |

webSocketClient.bindCall(nameOrOptions) ⇒ function

Returns a new function which calls the given method name by binding the function to this RPC instance and the given method name (or options object).

For example:

const subtract = rpc.bindCall('subtract');
subtract(10, 3).then(result => console.log(result)) // 7

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | nameOrOptions | string | Object | The method name or an options object | | nameOrOptions.name | string | The method name | | nameOrOptions.timeout | number | A maximum time (in milliseconds) to wait for a response. The returned promise will reject after this time. |

webSocketClient.notify(nameOrOptions, ...args) ⇒ Promise

Execute a notification on the remote instance, by sending a JSON-RPC request object to our write stream.

If no write stream has been set, the method call will be buffered until a write stream is set (setWriteStream).

This function resolves as soon as the request object has been buffered, but does not wait for the remote instance to have actually received the request object.

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | nameOrOptions | string | Object | The method name or an options object | | nameOrOptions.name | string | The method name | | ...args | * | |

webSocketClient.bindNotify(nameOrOptions) ⇒ function

Returns a new function which sends a notification with the given method name by binding the function to this RPC instance and the given method name (or options object).

For example:

const userDeleted = rpc.bindNotify('userDeleted');
userDeleted(123)

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | nameOrOptions | string | Object | The method name or an options object | | nameOrOptions.name | string | The method name | | nameOrOptions.timeout | number | A maximum time (in milliseconds) to wait for a response. The returned promise will reject after this time. |

webSocketClient.start()

Establish the WebSocket connection, and automatically reconnect after an network error or timeout.

Kind: instance method of WebSocketClient

webSocketClient.stop(code, reason)

Close the active WebSocket connection, and stop reconnecting. If there is no active connection the code and reason params are ignored.

Kind: instance method of WebSocketClient

| Param | Type | Default | Description | | --- | --- | --- | --- | | code | number | | Must be equal to 1000 or in the range 3000 to 4999 inclusive | | reason | string | "Normal Closure" | Must be 123 bytes or less (utf8) |

webSocketClient.closeConnection(code, reason) ⇒ boolean

Close the active WebSocket connection and reconnect if reconnects are enabled. If there is no active connection the code and reason params are ignored.

Kind: instance method of WebSocketClient

| Param | Type | Description | | --- | --- | --- | | code | number | Must be equal to 1000 or in the range 3000 to 4999 inclusive | | reason | string | Must be 123 bytes or less (utf8) |

"error" (error)

This event is fired if an uncaught error occurred

Most errors end up at the caller of our functions or at the remote peer, instead of this event. Note that if you do not listen for this event on node.js, your process might exit.

Kind: event emitted by WebSocketClient

| Param | Type | | --- | --- | | error | Error |

"protocolError" (error)

This event is fired if our peer sent us something that we were unable to parse.

These kind of errors do not end up at the 'error' event

Kind: event emitted by WebSocketClient

| Param | Type | | --- | --- | | error | Error |

"pingSuccess" (delay)

The most recent ping sent to our peer succeeded

Kind: event emitted by WebSocketClient

| Param | Type | Description | | --- | --- | --- | | delay | number | How long the ping took to resolve (in milliseconds) |

"pingFail" (consecutiveFails, error)

The most recent ping sent to our peer timed out or resulted in an error

Kind: event emitted by WebSocketClient

| Param | Type | Description | | --- | --- | --- | | consecutiveFails | number | The amount of consecutive pings that failed | | error | Error | |

"webSocketConnecting"

The WebSocket connection is being established but is not yet open.

Kind: event emitted by WebSocketClient

"webSocketOpen"

The WebSocket connection is now open and all pending RPC calls will be flushed to the server

Kind: event emitted by WebSocketClient

"webSocketError" (error)

The WebSocket API raised an error.

Kind: event emitted by WebSocketClient

| Param | Type | Description | | --- | --- | --- | | error | window.Event | ws.ErrorEvent | When running in node.js this contains an ErrorEvent from the "ws" library, interesting properties include message (string) and error (Error) However when run in a browser, this will contain a plain Event without any useful error information. |

"webSocketClose"

The WebSocket connection has been (half) closed by either side.

Kind: event emitted by WebSocketClient

| Type | | --- | | Object |

"webSocketClose" (info)

This event is fired if the WebSocket connection has been closed. A new connection might be established after this event if the reconnect option is enabled.

Kind: event emitted by WebSocketClient

| Param | Type | | --- | --- | | info | Object |

Example

rpc = new WebSocketClient(...);
rpc.on('webSocketClose', ({code, reason}) => {
  if (reason === closeCodes.POLICY_VIOLATION) {
    rpc.stop(); // stop reconnecting
  }
});