UNPKG

rpc-websocket-client

Version:

<p align="center"> <a href="https://github.com/radarsu/rpc-websocket-client/" target="blank"><img src="https://raw.githubusercontent.com/radarsu/rpc-websocket-client/master/assets/logo.png" alt="rpc-websocket-client" /></a><br/> <strong>Fast JSO

305 lines (303 loc) 11.4 kB
var v1 = require('uuid/v1'); var WebSocket = require('isomorphic-ws'); var RpcVersions; (function (RpcVersions) { RpcVersions["RPC_VERSION"] = "2.0"; })(RpcVersions || (RpcVersions = {})); var RpcWebSocketClient = /** @class */ (function () { // constructor /** * Does not start WebSocket connection! * You need to call connect() method first. * @memberof RpcWebSocketClient */ function RpcWebSocketClient() { this.idAwaiter = {}; this.onOpenHandlers = []; this.onAnyMessageHandlers = []; this.onNotification = []; this.onRequest = []; this.onSuccessResponse = []; this.onErrorResponse = []; this.onErrorHandlers = []; this.onCloseHandlers = []; this.config = { responseTimeout: 10000 }; this.ws = undefined; } // public /** * Starts WebSocket connection. Returns Promise when connection is established. * @param {string} url * @param {(string | string[])} [protocols] * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.connect = function (url, protocols) { this.ws = new WebSocket(url, protocols); return this.listen(); }; // events RpcWebSocketClient.prototype.onOpen = function (fn) { this.onOpenHandlers.push(fn); }; /** * Native onMessage event. DO NOT USE THIS unless you really have to or for debugging purposes. * Proper RPC events are onRequest, onNotification, onSuccessResponse and onErrorResponse (or just awaiting response). * @param {RpcMessageEventFunction} fn * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.onAnyMessage = function (fn) { this.onAnyMessageHandlers.push(fn); }; RpcWebSocketClient.prototype.onError = function (fn) { this.onErrorHandlers.push(fn); }; RpcWebSocketClient.prototype.onClose = function (fn) { this.onCloseHandlers.push(fn); }; /** * Appends onmessage listener on native websocket with RPC handlers. * If onmessage function was already there, it will call it on beggining. * Useful if you want to use RPC WebSocket Client on already established WebSocket along with function changeSocket(). * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.listenMessages = function () { var _this = this; var previousOnMessage; if (this.ws.onmessage) { previousOnMessage = this.ws.onmessage.bind(this.ws); } this.ws.onmessage = function (e) { if (previousOnMessage) { previousOnMessage(e); } for (var _i = 0, _a = _this.onAnyMessageHandlers; _i < _a.length; _i++) { var handler = _a[_i]; handler(e); } var data = JSON.parse(e.data.toString()); if (_this.isNotification(data)) { // notification for (var _b = 0, _c = _this.onNotification; _b < _c.length; _b++) { var handler = _c[_b]; handler(data); } } else if (_this.isRequest(data)) { // request for (var _d = 0, _e = _this.onRequest; _d < _e.length; _d++) { var handler = _e[_d]; handler(data); } // responses } else if (_this.isSuccessResponse(data)) { // success for (var _f = 0, _g = _this.onSuccessResponse; _f < _g.length; _f++) { var handler = _g[_f]; handler(data); } // resolve awaiting function _this.idAwaiter[data.id](data.result); } else if (_this.isErrorResponse(data)) { // error for (var _h = 0, _j = _this.onErrorResponse; _h < _j.length; _h++) { var handler = _j[_h]; handler(data); } // resolve awaiting function _this.idAwaiter[data.id](data.error); } }; }; // communication /** * Creates and sends RPC request. Resolves when appropirate response is returned from server or after config.responseTimeout. * @param {string} method * @param {*} [params] * @returns * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.call = function (method, params) { var _this = this; return new Promise(function (resolve, reject) { var data = _this.buildRequest(method, params); // give limited time for response var timeout; if (_this.config.responseTimeout) { timeout = setTimeout(function () { // stop waiting for response delete _this.idAwaiter[data.id]; reject("Awaiting response to \"" + method + "\" with id: " + data.id + " timed out."); }, _this.config.responseTimeout); } // expect response _this.idAwaiter[data.id] = function (responseData) { // stop timeout clearInterval(timeout); // stop waiting for response delete _this.idAwaiter[data.id]; if (_this.isRpcError(responseData)) { reject(responseData); return; } resolve(responseData); }; var json = JSON.stringify(data); _this.ws.send(json); }); }; /** * Creates and sends RPC Notification. * @param {string} method * @param {*} [params] * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.notify = function (method, params) { this.ws.send(JSON.stringify(this.buildNotification(method, params))); }; // setup /** * You can provide custom id generation function to replace default uuid/v1. * @param {() => string} idFn * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.customId = function (idFn) { this.idFn = idFn; }; /** * Removed jsonrpc from sent messages. Good if you don't care about standards or need better performance. * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.noRpc = function () { this.buildRequest = this.buildRequestBase; this.buildNotification = this.buildNotificationBase; this.buildRpcSuccessResponse = this.buildRpcSuccessResponseBase; this.buildRpcErrorResponse = this.buildRpcErrorResponseBase; }; /** * Allows modifying configuration. * @param {RpcWebSocketConfig} options * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.configure = function (options) { Object.assign(this.config, options); }; /** * Allows you to change used native WebSocket client to another one. * If you have already-connected WebSocket, use this with listenMessages(). * @param {WebSocket} ws * @memberof RpcWebSocketClient */ RpcWebSocketClient.prototype.changeSocket = function (ws) { this.ws = ws; }; // private // events RpcWebSocketClient.prototype.listen = function () { var _this = this; return new Promise(function (resolve, reject) { _this.ws.onopen = function (e) { for (var _i = 0, _a = _this.onOpenHandlers; _i < _a.length; _i++) { var handler = _a[_i]; handler(e); } resolve(e); }; // listen for messages _this.listenMessages(); // called before onclose _this.ws.onerror = function (e) { for (var _i = 0, _a = _this.onErrorHandlers; _i < _a.length; _i++) { var handler = _a[_i]; handler(e); } }; _this.ws.onclose = function (e) { for (var _i = 0, _a = _this.onCloseHandlers; _i < _a.length; _i++) { var handler = _a[_i]; handler(e); } reject(e); }; }); }; // request RpcWebSocketClient.prototype.buildRequest = function (method, params) { var data = this.buildRequestBase(method, params); data.jsonrpc = RpcVersions.RPC_VERSION; return data; }; RpcWebSocketClient.prototype.buildRequestBase = function (method, params) { var data = {}; data.id = this.idFn(); data.method = method; if (params) { data.params = params; } return data; }; // notification RpcWebSocketClient.prototype.buildNotification = function (method, params) { var data = this.buildNotificationBase(method, params); data.jsonrpc = RpcVersions.RPC_VERSION; return data; }; RpcWebSocketClient.prototype.buildNotificationBase = function (method, params) { var data = {}; data.method = method; if (params) { data.params = params; } return data; }; // success response RpcWebSocketClient.prototype.buildRpcSuccessResponse = function (id, result) { var data = this.buildRpcSuccessResponseBase(id, result); data.jsonrpc = RpcVersions.RPC_VERSION; return data; }; RpcWebSocketClient.prototype.buildRpcSuccessResponseBase = function (id, result) { var data = {}; data.id = id; data.result = result; return data; }; // error response RpcWebSocketClient.prototype.buildRpcErrorResponse = function (id, error) { var data = this.buildRpcErrorResponseBase(id, error); data.jsonrpc = RpcVersions.RPC_VERSION; return data; }; RpcWebSocketClient.prototype.buildRpcErrorResponseBase = function (id, error) { var data = {}; data.id = id; data.error = error; return data; }; RpcWebSocketClient.prototype.idFn = function () { return v1(); }; // tests RpcWebSocketClient.prototype.isNotification = function (data) { return !data.id; }; RpcWebSocketClient.prototype.isRequest = function (data) { return data.method; }; RpcWebSocketClient.prototype.isSuccessResponse = function (data) { return data.hasOwnProperty("result"); }; RpcWebSocketClient.prototype.isErrorResponse = function (data) { return data.hasOwnProperty("error"); }; RpcWebSocketClient.prototype.isRpcError = function (data) { var _a; return typeof ((_a = data) === null || _a === void 0 ? void 0 : _a.code) !== 'undefined'; }; return RpcWebSocketClient; }()); export { RpcVersions, RpcWebSocketClient }; //# sourceMappingURL=rpc-websocket-client.es5.js.map