UNPKG

twiliojs-api

Version:

Module to invoke twilio.com services

150 lines (117 loc) 5.45 kB
/* * Module's dependencies */ var request = require("request"); var Util = function(settings) { var self = this; // For each method metadata, it adds a new public method to the instance this.hook = function (target, methods) { if ( !target || typeof target !== 'object' ) throw new Error("Invalid 'target' argument. It must be an object instance."); if ( !methods || typeof methods !== 'object' ) throw new Error("Invalid 'methods' argument. It must be an object instance."); // creates every single method Object.keys(methods) .forEach(function (groupName) { var group = methods[groupName]; Object.keys(group) .forEach(function (methodName) { var info = group[methodName]; validatesMethodInfo(groupName,info); target[methodName] = createMethod(methodName, info); }); }); }; this.validateParams = function (data, params) { if (!data || typeof data !== 'object') throw new Error("Invalid 'data' argument. It must be an object instance."); if (!(params instanceof Array)) throw new Error("Invalid 'params' argument. It must be an string array."); for (var index in params) { var param = params[index]; if (data[param]===undefined || data[param]===null) { return new Error("'" + param + "' option is required."); } } }; this.buildResponse = function (response) { var res = { headers: response.headers, statusCode: response.statusCode }; if (response.body) res.body = parseBody(response.body); return res; }; var parseBody = function (body) { if( typeof body === 'string') return JSON.parse(body); if( typeof body === 'object') return body; }; var getUserKey = function(username, password) { return username + ":" + password; }; var createMethod = function(name, info) { var requiredParams = getParamsFromPath(info.path); return function(options, cb) { // manage optional options if (!cb && typeof options === 'function') { cb = options; options = null; }; // validates cb cb = cb || function(err) { if(err) throw err; }; if (typeof cb !== 'function') throw new Error("'cb' argument is invalid."); // validates options options = options || {}; if (typeof options !== 'object') return cb(new Error("'options' argument is invalid.")); // validates required parameters var err = self.validateParams(options, requiredParams); if (err) return cb(err); // var endpoint = settings.apiEndpoint + supplant(info.path, options); // Sets HTTP request options var reqOptions = { method: info.method || "GET", url: endpoint + '.json', headers: { Authorization: "Basic " + new Buffer(settings.accountSid + ":" + settings.accountToken).toString('base64') } }; if (reqOptions.method==="GET") { reqOptions.json = options; } else { reqOptions.form = options; } // Invokes Twilio's servers request(reqOptions, function (err, response) { if (err) return cb (new Error( "There was an error executing method '" + name + "'. " + err.message )); var twilioResponse = self.buildResponse(response); if (response.statusCode >= 400) return cb (new Error( "Twilio reports an error executing method '" + name + "'. Message: '" + twilioResponse.body.message + "'. Code: " + twilioResponse.body.code + "'")); cb (null, twilioResponse); }); }; }; var validatesMethodInfo = function(groupName, info) { // validate params info.params = info.params || {} if (typeof info.params !== 'object') throw new Error("Invalid method's params. " + JSON.stringify(info)); // validate method info.method = info.method || "GET"; if (typeof info.method !== 'string') throw new Error("Invalid HTTP method. " + JSON.stringify(info)); // Twilio 'account' is the root resource for all calls // see: http://www.twilio.com/docs/api/rest/account if (groupName!="account") { // validates path if (!(info.path) || typeof info.path != 'string') throw new Error("Invalid method's path. " + JSON.stringify(info)); if (info.path[0]!=='/') throw new Error("Method's path must start with '/' character. " + JSON.stringify(info)); }; }; var getParamsFromPath = function(path) { var results = path.match(/{([^{}]*)}/g); return results ? results.map(function(m) { return m.substring(1, m.length-1); }) : []; }; var supplant = function(pattern, data) { return pattern.replace(/{([^{}]*)}/g, function (a, b) { var r = data[b]; return typeof r === 'string' || typeof r === 'number' ? r : r.toString(); }); }; }; module.exports = Util;