jsonrpc-dispatch
Version:
An unopinionated JSONRPC dispatcher for JavaScript
224 lines (177 loc) • 6.79 kB
JavaScript
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);
;