UNPKG

webu

Version:

IrChain JavaScript API, middleware to talk to a irchain node over RPC

170 lines (151 loc) 4.55 kB
/* This file is part of webu.js. webu.js is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. webu.js is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with webu.js. If not, see <http://www.gnu.org/licenses/>. */ /** * @file method.js * @author Marek Kotewicz <marek@ethdev.com> * @date 2015 */ var utils = require('../utils/utils'); var errors = require('./errors'); var Method = function(options) { this.name = options.name; this.call = options.call; this.params = options.params || 0; this.inputFormatter = options.inputFormatter; this.outputFormatter = options.outputFormatter; this.requestManager = null; }; Method.prototype.setRequestManager = function(rm) { this.requestManager = rm; }; /** * Should be used to determine name of the jsonrpc method based on arguments * * @method getCall * @param {Array} arguments * @return {String} name of jsonrpc method * @param args */ Method.prototype.getCall = function(args) { return utils.isFunction(this.call) ? this.call(args) : this.call; }; /** * Should be used to extract callback from array of arguments. Modifies input param * * @method extractCallback * @param {Array} arguments * @return {Function|Null} callback, if exists * @param args */ Method.prototype.extractCallback = function(args) { if (utils.isFunction(args[args.length - 1])) { return args.pop(); // modify the args array! } }; /** * Should be called to check if the number of arguments is correct * * @method validateArgs * @param {Array} arguments * @throws {Error} if it is not * @param args */ Method.prototype.validateArgs = function(args) { if (args.length !== this.params) { throw errors.InvalidNumberOfRPCParams(); } }; /** * Should be called to format input args of method * * @method formatInput * @return {Array} * @param args */ Method.prototype.formatInput = function(args) { if (!this.inputFormatter) { return args; } return this.inputFormatter.map(function(formatter, index) { return formatter ? formatter(args[index]) : args[index]; }); }; /** * Should be called to format output(result) of method * * @method formatOutput * @return {Object} * @param result */ Method.prototype.formatOutput = function(result) { return this.outputFormatter && result ? this.outputFormatter(result) : result; }; /** * Should create payload from given input args * * @method toPayload * @param {Array} args * @return {Object} */ Method.prototype.toPayload = function(args) { var call = this.getCall(args); var callback = this.extractCallback(args); var params = this.formatInput(args); this.validateArgs(params); return { method : call, params : params, callback: callback, }; }; Method.prototype.attachToObject = function(obj) { var func = this.buildCall(); func.call = this.call; var name = this.name.split('.'); if (name.length > 1) { obj[name[0]] = obj[name[0]] || {}; obj[name[0]][name[1]] = func; } else { obj[name[0]] = func; } }; Method.prototype.buildCall = function() { var method = this; var send = function() { var payload = method.toPayload(Array.prototype.slice.call(arguments)); if (payload.callback) { return method.requestManager.sendAsync( payload, function(err, result) { payload.callback(err, method.formatOutput(result)); }); } return method.formatOutput(method.requestManager.send(payload)); }; send.request = this.request.bind(this); return send; }; /** * Should be called to create pure JSONRPC request which can be used in batch request * * @method request * @param {...} arguments * @return {Object} jsonrpc request */ Method.prototype.request = function() { var payload = this.toPayload(Array.prototype.slice.call(arguments)); payload.format = this.formatOutput.bind(this); return payload; }; module.exports = Method;