jest
Version:
JavaScriptational State Transfer. JS restful API layer with Mongoose based resources. Inspired by python Tastypie
257 lines (230 loc) • 9.06 kB
JavaScript
var _ = require('underscore'),
Class = require('sji'),
Resource = require('./resource');
Validation = require('./mongoose_validation');
var MongooseResource = module.exports = Resource.extend({
init:function (model) {
this._super();
this.model = model;
this.default_filters = {};
this.default_query = function (query) {
return query;
};
this.validation = new Validation(model);
},
run_query: function(req,queryset, callback)
{
queryset.exec(callback);
},
show_fields : function(){
return this.fields || _.map(this.model.schema.tree,function(value,key)
{
return key;
});
},
get_object:function (req, id, callback) {
var self = this;
var query = this.default_query(this.model.findOne(this.default_filters));
query = query.where('_id',id);
this.authorization.limit_object(req, query, function (err, query) {
if (err) callback(err);
else {
self.run_query(req,query,callback);
}
});
},
get_objects:function (req, filters, sorts, limit, offset, callback) {
var self = this;
var query = this.default_query(this.model.find(this.default_filters));
var count_query = this.default_query(this.model.count(this.default_filters));
for (var filter in filters) {
if(filter == 'or')
{
var filter_value = _.map(filters[filter],function(or_filters)
{
var or_filter_value = {};
for (var filter in or_filters) {
var splt = filter.split('__');
var query_op = null;
var query_key = filter;
var query_value = or_filters[filter];
if (splt.length > 1) {
query_key = splt[0];
query_op = splt[1];
}
if(self.model.schema.paths[query_key])
{
if(self.model.schema.paths[query_key].options.type == Boolean)
query_value = query_value.toLowerCase().trim() == 'true';
if(self.model.schema.paths[query_key].options.type == Number)
query_value = Number(query_value.trim());
}
var current_or_filter_value = or_filter_value[query_key] || {};
if(query_op)
current_or_filter_value['$' + query_op] = query_value;
else
current_or_filter_value = query_value;
or_filter_value[query_key] = current_or_filter_value;
}
return or_filter_value;
});
console.log(filter_value);
query.or(filter_value);
}
else
{
var splt = filter.split('__');
var query_op = null;
var query_key = filter;
var query_value = filters[filter];
if (splt.length > 1) {
query_key = splt[0];
query_op = splt[1];
}
if(self.model.schema.paths[query_key])
{
if(self.model.schema.paths[query_key].options.type == Boolean)
query_value = typeof(query_value) == 'string' ? query_value.toLowerCase().trim() == 'true' : !!query_value;
if(self.model.schema.paths[query_key].options.type == Number)
query_value = typeof(query_value) == 'string' ? Number(query_value.trim()) : Number(query_value);
}
if(query_op)
{
if(query_op == 'maxDistance')
query_value = Number(query_value);
query.where(query_key)[query_op](query_value);
//count_query.where(query_key)[query_op](query_value);
}
else
{
query.where(query_key, query_value);
//count_query.where(query_key, query_value);
}
}
}
var default_sort = query.options.sort || [];
default_sort = _.filter(default_sort,function(sort) {
var field = sort[0];
return _.all(sorts,function(sort_query) {
return sort_query.field != field;
});
});
query.options.sort = [];
for (var i = 0; i < sorts.length; i++) {
var sort_arg = {};
sort_arg[sorts[sorts.length-1-i].field] = sorts[sorts.length-1-i].type;
query.sort(sort_arg);
}
for(var i=0; i<default_sort.length; i++)
query.options.sort.push(default_sort[i]);
if(limit > 0)
query.limit(limit);
if(offset > 0)
query.skip(offset);
var results = null, count = null;
function on_finish() {
if (results != null && count != null) {
var final = {
objects:results,
meta:{
total_count:count,
offset:offset,
limit:limit
}
};
callback(null, final);
}
}
self.authorization.limit_object_list(req, query, function (err, query) {
if (err) return callback(err);
for(var key in query._conditions){
count_query._conditions[key] = query._conditions[key];
}
self.run_query(req,query,function (err, objects,counter) {
if (err) callback(err);
else {
results = objects;
if(!(limit > 0))
count = counter || objects.length;
on_finish();
}
});
if(limit > 0) {
self.run_query(req,count_query,function (err, counter) {
if (err) callback(err);
else {
count = counter;
on_finish();
}
});
}
});
// self.authorization.limit_object_list(req, count_query, function (err, count_query) {
// if (err) callback(err);
// else
// });
},
create_obj:function (req, fields, callback) {
var self = this;
var object = new self.model();
for (var field in fields) {
object[field] = fields[field];
}
self.authorization.edit_object(req, object, function (err, object) {
if (err) callback(err);
else {
object.save(function (err, object) {
callback(self.elaborate_mongoose_errors(err), object);
});
}
});
},
update_obj:function (req, object, callback) {
var self = this;
self.authorization.edit_object(req, object, function (err, object) {
if (err) callback(err);
else {
object.save(function (err, object) {
callback(self.elaborate_mongoose_errors(err), object);
});
}
});
},
delete_obj:function (req, object, callback) {
object.remove(function (err) {
if (err) callback(err);
else
callback(null, {});
});
},
elaborate_mongoose_errors:function (err) {
if (err && err.errors) {
for (var error in err.errors) {
err.errors[error] = this.validation.elaborate_mongoose_error(error, err.errors[error]);
}
}
return err;
},
/**
* Sets values from fields in object
* @param object
* @param fields
*/
setValues:function(object,fields) {
var paths = {};
var current_path = [];
var iterateFields = function(fields) {
_.each(fields,function(value,key) {
current_path.push(key);
if(value && typeof(value) == 'object' && !Array.isArray(value))
iterateFields(value);
else
paths[current_path.join('.')] = value;
current_path.pop();
})
};
iterateFields(fields);
this._super(object,paths);
return object;
}
});