blob: 6e3a324fd6bd2b0d08fac87919fc97515ccbf53f [file] [log] [blame]
var inflection = require('inflection');
var pathProxy = require('path-proxy');
var Q = require('q');
var noop = function () {
};
var Builder = function (baseObj, resources) {
this.baseObj = baseObj;
this.resources = resources;
};
Builder.prototype.build = function () {
var self = this;
Object.keys(this.resources).forEach(function (key) {
//console.log('building ' + key);
self.buildResource(self.resources[key]);
});
};
Builder.prototype.buildResource = function (resource) {
resource.links.forEach(this.buildAction, this);
};
Builder.prototype.buildAction = function (action) {
var actionName = action.title;
var properties = action.properties;
var requiredProps = action.required;
// HACKY special case for members bulk add and send MIME endpoints
var path = action.href.replace(/\.json/gi, '').replace(/\.mime/gi, '');
var constructor = pathProxy.pathProxy(this.baseObj, path);
constructor.prototype[getName(actionName)] = function (data, fn) {
var deferred = Q.defer();
var requestPath = action.href;
var pathParams = action.href.match(/{[^}]+}/g) || [];
if (typeof data === 'function') {
fn = data;
data = undefined;
}
if (!fn) fn = noop;
var err;
if (this.params.length !== pathParams.length) {
err = new Error('Invalid number of params in path (expected ' + pathParams.length + ', got ' + this.params.length + ').');
return rejectError(err, deferred, fn);
}
this.params.forEach(function (param) {
requestPath = requestPath.replace(/{[^}]+}/, param);
});
// check required payload properties
if (requiredProps && requiredProps.length > 0) {
if (!data) {
err = new Error('Missing parameters.');
}
else {
for (var i = 0; i < requiredProps.length; i++) {
var prop = requiredProps[i];
if (typeof data[prop] === 'undefined') {
err = new Error('Missing parameter \'' + prop + '\'');
break;
}
}
}
}
if (err) {
return rejectError(err, deferred, fn);
}
// check payload property types
for (var key in properties) {
if (data && data[key]) {
var type = properties[key].type;
var dataType = Array.isArray(data[key]) ? 'array' : typeof data[key];
if (Array.isArray(type)) {
if (type.indexOf(dataType) === -1) {
err = new Error('Invalid parameter type. ' + key + ' must be of type: ' + type + '.');
break;
}
}
else if (dataType !== type) {
err = new Error('Invalid parameter type. ' + key + ' must be of type: ' + type + '.');
break;
}
}
}
if (err) {
return rejectError(err, deferred, fn);
}
this.client = this.base;
return this.client.request(action.method, requestPath, data, fn);
};
}
;
function rejectError(err, deferred, fn) {
deferred.reject(err);
fn(err);
return deferred.promise;
}
function getName(name) {
name = name.toLowerCase();
name = inflection.dasherize(name).replace(/-/g, '_');
name = inflection.camelize(name, true);
return name;
}
exports.build = function (baseObj, resources) {
var b = new Builder(baseObj, resources);
b.build();
};