@akala/json-rpc-ws
Version:
json-rpc websocket transport
116 lines • 3.77 kB
JavaScript
import { Base } from './base.js';
import debug from 'debug';
const logger = debug('akala:json-rpc-ws');
import { SocketProtocolAdapter } from '@akala/core';
/**
* json-rpc-ws connection
*
* @constructor
* @param {Socket} socket - web socket for this connection
* @param {Object} parent - parent that controls this connection
*/
export class JsonNDRpcSocketAdapter extends SocketProtocolAdapter {
constructor(socket) {
const accumulator = [];
super({
receive: (data) => {
if (typeof (data) !== 'string')
data = data.toString('utf8');
let messages = data.split('\n');
if (messages.length == 1) {
accumulator.push(messages[0]);
return [];
}
if (accumulator.length)
messages = accumulator.concat(messages);
messages = messages.filter(d => d);
return messages.map(data => JSON.parse(data));
},
send: (data) => JSON.stringify(data) + '\n',
}, socket);
}
}
export default class Client extends Base {
socketConstructor;
options;
constructor(socketConstructor, options) {
super('client');
this.socketConstructor = socketConstructor;
this.options = options;
logger('new Client');
}
socket;
/**
* Connect to a json-rpc-ws server
*
* @param {String} address - url to connect to i.e. `ws://foo.com/`.
* @param {function} callback - optional callback to call once socket is connected
* @public
*/
connect(address, callback) {
logger('Client connect %s', address);
if (this.isConnected())
throw new Error('Already connected');
let opened = false;
const socket = this.socket = this.socketConstructor(address, this.options);
socket.once('open', () => {
// The client connected handler runs scoped as the socket so we can pass
// it into our connected method like thisk
this.connected(socket);
opened = true;
if (callback)
callback.call(this);
});
if (callback)
this.socket.once('error', function socketError(err) {
if (!opened) {
callback.call(self, err);
}
});
}
/**
* Test whether we have a connection or not
*
* @returns {Boolean} whether or not we have a connection
* @public
*/
isConnected() {
return Object.keys(this.connections).length !== 0;
}
/**
* Return the current connection (there can be only one)
*
* @returns {Object} current connection
* @public
*/
getConnection() {
const ids = Object.keys(this.connections);
return this.connections[ids[0]];
}
/**
* Close the current connection
*/
disconnect() {
if (!this.isConnected())
throw new Error('Not connected');
const connection = this.getConnection();
return connection.hangup();
}
/**
* Send a method request
*
* @param {String} method - name of method
* @param {Array} params - optional parameters for method
* @param {function} callback - optional reply handler
* @public
* @todo allow for empty params aka arguments.length === 2
*/
send(method, params, callback) {
logger('send %s', method);
if (!this.isConnected())
throw new Error('Not connected');
const connection = this.getConnection();
connection.sendMethod(method, params, callback);
}
}
//# sourceMappingURL=shared-client.js.map