UNPKG

jsonrpc-dispatch

Version:

An unopinionated JSONRPC dispatcher for JavaScript

224 lines (177 loc) 6.79 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _freeze = require('babel-runtime/core-js/object/freeze'); var _freeze2 = _interopRequireDefault(_freeze); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _extends2 = require('babel-runtime/helpers/extends'); var _extends3 = _interopRequireDefault(_extends2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _uuid = require('uuid'); var _uuid2 = _interopRequireDefault(_uuid); var _errors = require('./errors'); var _errors2 = _interopRequireDefault(_errors); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var JSONRPCVersion = '2.0'; /** * JSONRPC class based on the JSONRPC specification[0]. This object handles creating JSONRPC * requests and notification objects and managing resolving responses. * * @see {@link http://json-rpc.org/wiki/specification} */ var JSONRPC = function () { /** * Initializes a JSONRPC instance. * @param {function} dispatcher - A function which takes a single argument for * the JSONRPC object to send to the RPC server. * @param {object} methods - The JSONRPC methods to handle. */ function JSONRPC(dispatcher) { var methods = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; (0, _classCallCheck3.default)(this, JSONRPC); this.version = JSONRPCVersion; this.deferreds = {}; this.methods = methods; this.dispatcher = dispatcher; } /** * Sends the given JSONPRC message using the dispatcher provided. * @param {object} message - A JSONPRC 2.0 message object. */ (0, _createClass3.default)(JSONRPC, [{ key: 'send', value: function send(message) { var data = (0, _extends3.default)({}, message); data.jsonrpc = this.version; this.dispatcher(data); } /** * Create a notification object for the given method and params. * @see {@link http://www.jsonrpc.org/specification#notification|JSONRPC Notifications} * * @param {string} method - The RPC method to execute * @param {object[]} params - The parameters to execute with the method. * @returns {object} JSONRPC notification object */ }, { key: 'notification', value: function notification(method) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; this.send({ method: method, params: params }); } /** * Create a request object for the given method and params and passes the result to * next(err, result). * @see {@link http://www.jsonrpc.org/specification#request_object|JSONRPC Requests} * * @param {string} method - The RPC method to execute * @param {object[]} params - The parameters to execute with the method. * @returns {Promise} which is resolved with the response value. */ }, { key: 'request', value: function request(method) { var _this = this; var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; return new _promise2.default(function (resolve, reject) { var id = _uuid2.default.v4(); // Save the resolve/reject callbacks as a deferred. We do this because // the response may not occur within the scope of the dispatch method. Example // Cross-Domain messaging is sent over postMessage but received via the // message event. _this.deferreds[id] = { resolve: resolve, reject: reject }; _this.send({ id: id, method: method, params: params }); }); } /** * Handles a JSONRPC message for the following scenarios: * request - Executes the method defined and passes the result to dispatch * response - Resolves the promise associated with the id on the response * notification - Executes the method defined * * @param {object} message - The JSONRPC message to handle. */ }, { key: 'handle', value: function handle(message) { // Requests and notifications have methods defined. if (message.method) { // Requests have ids if (message.id) { this.handleRequest(message); // Notifications have no ids } else { this.handleNotification(message); } // Responses have no methods, but have an id } else if (message.id) { this.handleResponse(message); } } /** * Handle a JSONRPC response object and resolve the promise associated to the * originating request. * @param {object} response - The JSONRPC response object to handle. */ }, { key: 'handleResponse', value: function handleResponse(response) { var deferred = this.deferreds[response.id]; if (deferred === undefined) { return; } if (response.error) { deferred.reject(response.error); } else { deferred.resolve(response.result); } delete this.deferreds[response.id]; } /** * Handle a JSONRPC request object and execute the method it specifies sending * the result to the dispatcher. * @param {object} request - The JSONRPC request object to handle. */ }, { key: 'handleRequest', value: function handleRequest(request) { var _this2 = this; var method = this.methods[request.method]; if (typeof method !== 'function') { var error = { message: 'The method ' + method + ' was not found.', code: _errors2.default.METHOD_NOT_FOUND }; this.send({ id: request.id, error: error }); return; } // Success method.apply(request, request.params).then(function (result) { _this2.send({ id: request.id, result: result }); // Error }).catch(function (message) { var error = { message: message, code: _errors2.default.INTERNAL_ERROR }; _this2.send({ id: request.id, error: error }); }); } /** * Handle a JSONRPC notification request and execute the method it specifies. * @param {object} request - The JSONRPC notification object to handle. */ }, { key: 'handleNotification', value: function handleNotification(request) { var method = this.methods[request.method]; if (method && typeof method === 'function') { method.apply(request, request.params); } } }]); return JSONRPC; }(); exports.default = (0, _freeze2.default)(JSONRPC);