alphascript-server
Version:
CRUD operations for mongo and other functionalities to get started quickly in any CMS project
392 lines (329 loc) • 14.2 kB
JavaScript
var api = require('../../../');
var mongoose = require('mongoose');
var formidable = require('formidable');
var Q = require('q');
var moment = require('moment');
var objectPath = require("object-path");
var path = require('path');
var fs = require('fs');
var path = require('path');
var main = module.exports = {
_list: function (req, res) {
main.list(req, function (err, items) {
if (err) return res.status(500).send(err);
res.json(items);
});
},
list: function (req, callback) {
var entity = req.entity;
var id = req.params.id;
if (!entity.collection) return callback("O seu pedido não pode ser processado");
var params = { query: {}, populate: "", sort: {}, limit: 0, select: "" };
for (var param in params) {
if (!entity[param]) continue;
if (typeof entity[param] === 'function') {
params[param] = entity[param](req, id);
} else {
params[param] = entity[param] || params[param];
}
}
var promise = entity.collection(req);
if (id) {
params.query._id = id;
promise = promise.findOne(params.query);
} else {
promise = promise.find(params.query);
}
populateBuilder(promise, params.populate).limit(params.limit).select(params.select).sort(params.sort).lean().exec(function (err, data) {
if (err) {
api.error.log(err);
return callback(api.error.DB_GENERIC);
}
if (!id) {
if (typeof entity.filter === 'function') data = data.filter(entity.filter);
if (typeof entity.map === 'function') data = data.map(entity.map);
if (typeof entity.forEach === 'function') data = data.forEach(entity.forEach);
if (typeof entity.reduce === 'function') data = data.reduce(entity.reduce);
if (typeof entity.onList === 'function') data = entity.onList(req, data);
} else {
if (typeof entity.map === 'function') data = entity.map(data);
}
callback(undefined, data);
});
},
fetch: function (req, res) {
if (!req.entity.collection) return res.status(404).send('O seu pedido não pode ser processado');
var query = { $and: [] };
if (typeof req.entity.query === 'function') query.$and.push(req.entity.query(req, null, 'list'));
else if (req.entity.query) query.$and.push(req.entity.query);
var select = "",
entitySelect = (req.entity.select || "").split(' ');
for (var property in req.query) {
var subquery = {};
try {
subquery[property] = JSON.parse(req.query[property]);
} catch (error) {
if (typeof req.query[property] === 'string') {
subquery[property] = new RegExp('.*' + req.query[property] + '.*', 'i');
} else if (req.query[property] instanceof Array) {
for (var x = 0; x < req.query[property].length; x++) {
try {
req.query[property][x] = JSON.parse(req.query[property][x]);
for (var subproperty in req.query[property][x]) {
if (typeof req.query[property][x][subproperty] === 'string') {
req.query[property][x][subproperty] = new RegExp('.*' + req.query[property][x][subproperty] + '.*', 'i');
}
}
} catch (error) {
req.query[property][x] = {};
}
}
subquery[property] = req.query[property];
} else {
subquery[property] = req.query[property];
}
}
query.$and.push(subquery);
if (entitySelect.indexOf(property) !== -1) {
select += property + " ";
}
}
if (query.$and.length === 0) query = {};
populateBuilder(req.entity.collection(req).find(query), typeof req.entity.populate === 'function' ? req.entity.populate(req) : req.entity.populate).select(select).lean().exec(function (err, data) {
if (err) {
api.error.log(err);
return res.status(500).send(api.error.DB_GENERIC);
}
res.json(data);
});
},
edit: function (req, res) {
if (!req.entity.collection) return res.status(404).send('O seu pedido não pode ser processado');
function callback(err, item) {
if (err) return res.status(500).send(err);
res.json(item);
}
if (req.headers.referer) {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
if (err) {
api.error.log(err);
return res.status(500).send("Não foi possível receber o seu pedido, por favor tente novamente");
}
var item = JSON.parse(fields.item);
editEntityItem(req, item, files, callback);
});
} else {
editEntityItem(req, req.body, {}, callback);
}
},
update: function (req, res) {
if (!req.entity.collection) return res.status(404).send('O seu pedido não pode ser processado');
var updateFields = req.body;
//update item
populateBuilder(req.entity.collection(req).findOneAndUpdate({ _id: req.params.id }, { $set: updateFields }, { new: true }), typeof req.entity.populate === 'function' ? req.entity.populate(req) : req.entity.populate).exec(function (err, item) {
if (err) {
if (err instanceof api.AlphaError) return res.status(500).send(err.message || err);
api.error.log(err);
return res.status(500).send(api.error.DB_GENERIC);
}
//log version
/*item.save(function (err) {
if (err) {
if (err instanceof api.AlphaError) return res.status(500).send(err.message || err);
api.error.log(err);
return res.status(500).send(api.error.DB_GENERIC);
}
*/
//emit through websockets
var activity = req.entityName + ".edit";
var websocket = typeof req.entity.websocket === 'function' ? req.entity.websocket(req) + '.' + activity : activity;
api.options.io.emit(websocket, item);
//log activity
api.activity.log(activity, item._id, req);
res.end();
//});
});
},
remove: function (req, res) {
//check entity authenticity
if (!req.entity.collection) return res.status(404).send('O seu pedido não pode ser processado');
//check remove eligibility
if (!req.entity.remove) return res.status(403).send('Não é permitido remover dados desta coleção: ' + req.entityName);
//check object dependencies
req.entity.remove(req.params.id, function (err) {
if (err) return res.status(409).send(err.message || err);
//remove object
req.entity.collection(req).remove({ _id: req.params.id }, function (err) {
if (err) {
if (err instanceof api.AlphaError) return res.status(500).send(err.message || err);
api.error.log(err);
return res.status(500).send(api.error.DB_GENERIC);
}
//emit through websockets
var activity = req.entityName + '.remove';
var websocket = typeof req.entity.websocket === 'function' ? req.entity.websocket(req) + '.' + activity : activity;
api.options.io.emit(websocket, req.params.id);
//log activity
api.activity.log(activity, req.params.id, req);
res.end();
});
}, req);
},
versions: function (req, res) {
if (!req.entity.collection) return res.status(404).send('O seu pedido não pode ser processado');
if (!req.entity.collection.versionedModel) return res.status(404).send('Os dados que selecionou não subscrevem a um controlo de versões');
req.entity.collection.versionedModel.find({ refId: req.params.id }).select("versions").lean().exec(function (err, data) {
if (err) return res.status(409).send(err.message || err);
res.json(data.versions);
});
},
xlsx: function (req, res) {
main.list(req, function (err, items) {
if (err) {
if (err instanceof api.AlphaError) return res.status(500).send(err.message || err);
return res.status(500).send(api.error.DB_GENERIC);
}
if (typeof items === 'undefined') return res.status(404).send("Não há registos para exportar");
if (!(items instanceof Array)) items = [items];
if (items.length === 0) return res.status(404).send("Não há registos para exportar");
//prepare header
var xlsHeader = {};
if (req.entity.cols instanceof Array) {
req.entity.cols.forEach(function (col) {
xlsHeader[col.field] = col.title;
});
}
else {
Object.keys(items[0]).forEach(function (col) {
xlsHeader[col] = col;
});
}
//prepare data
if (typeof req.entity.xlsx === 'function') items = req.entity.xlsx(items);
//on spreadsheet
var xls = { sheets: [] };
var filename = (req.entity.title || req.entityName) + ' ' + moment().format('YYYY-MM-DD') + '.xlsx';
xls.sheets.push({ header: xlsHeader, sheetName: (req.entity.title || req.entityName), items: items });
res.setHeader('Content-Type', 'application/vnd.openxmlformats');
res.setHeader("Content-Disposition", "attachment; filename=" + filename);
res.send(api.xlsx.fromJson(xls));
});
},
pdf: function (req, res) {
var next = typeof req.entity.pdf === 'function' ? req.entity.pdf : main.list;
next(req, function (err, items, ejsOptions, pdfOptions) {
if (err) {
if (err instanceof api.AlphaError) return res.status(500).send(err.message || err);
return res.status(500).send(api.error.DB_GENERIC);
}
if (typeof items === 'undefined') return res.status(404).send("Não há registos para exportar");
var data = { req: req, moment: moment, node_modules: path.resolve('./node_modules'), bower_components: path.resolve('./bower_components') };
if (req.params.id) data.item = items;
else data.items = items;
if (req.params.id) {
ejsOptions = ejsOptions || {
filename: req.entityName + '.pdf.ejs',
data: data
};
pdfOptions = pdfOptions || {
filepath: path.join(api.options.fsRoot, '/pdf/'),
filename: req.entityName + '.pdf',
preset: api.pdf.presets.A4_PORTRAIT
};
api.pdf.fromEjsToBuffer(ejsOptions, pdfOptions, function (err, buffer) {
if (err) {
api.error.log(err);
return res.status(500).send(api.error.PDF_GENERIC);
}
res.contentType("application/pdf");
res.send(buffer);
});
}
if (items.length === 0) return res.status(404).send("Não há registos para exportar");
});
}
};
function saveEntityItem(req, id, item, callback) {
if (id) {
populateBuilder(req.entity.collection(req).findOneAndUpdate({ _id: id }, { $set: item._doc }, { new: true }), typeof req.entity.populate === 'function' ? req.entity.populate(req) : req.entity.populate).exec(function (err, populatedItem) {
if (err) return callback(err);
//log version
populatedItem.save(function (err) {
if (err) return callback(err);
callback(null, populatedItem.toObject());
});
});
} else {
item.save(function (err) {
if (err) return callback(err);
//get populated item
populateBuilder(item, typeof req.entity.populate === 'function' ? req.entity.populate(req) : req.entity.populate).execPopulate().then(function (populatedItem) {
callback(null, populatedItem.toObject());
}, function (err) {
callback(err);
});
});
}
}
function populateBuilder(query, populates) {
if (!(populates instanceof Array)) populates = [populates];
populates.forEach(function (populate) {
if (typeof populate === 'string') {
var populateParts = populate.split(' ');
populateParts.forEach(function (populatePart) {
if (!populatePart) return;
query = query.populate(populatePart);
});
} else {
query = query.populate(populate);
}
});
return query;
}
function editEntityItem(req, item, files, callback) {
var before = req.params.id ? req.entity.beforeEdit : req.entity.beforeAdd;
var after = req.params.id ? req.entity.afterEdit : req.entity.afterAdd;
var validate = typeof req.entity.validate === 'function' ? req.entity.validate : api.skip;
validate(item, function (err) {
if (err) return callback(err.message || err);
//upload files
var promises = [];
for (var file in files) {
promises.push(api.document.upload(req, req.entityName, item._id, file, files[file]));
}
if (typeof item.toObject === 'function') item = item.toObject();
Q.all(promises).then(function (results) {
results.forEach(function (result) {
var keys = result.key.replace("[", ".").replace("]", "");
objectPath.set(item, keys, result.document);
});
//execute entity scripts, if any, before save
before(item, function (err, item) {
if (err) return callback(err.message || err);
//save object to db
if (!(item instanceof mongoose.Document)) item = new req.entity.collection(req)(item);
saveEntityItem(req, req.params.id, item, function (err, populatedItem) {
if (err) {
if (err instanceof api.AlphaError) return callback(err.message || err);
api.error.log(err);
return callback(api.error.DB_GENERIC);
}
//execute entity scripts, if any, after save
after(populatedItem, function (err, populatedItem) {
if (err) return callback(err.message || err);
//emit through websockets
var activity = req.entityName + "." + (req.params.id ? "edit" : "new");
var websocket = typeof req.entity.websocket === 'function' ? req.entity.websocket(req) + '.' + activity : activity;
api.options.io.emit(websocket, populatedItem);
//log activity
api.activity.log(activity, populatedItem._id, req);
callback(undefined, populatedItem);
}, req);
});
}, req);
}, function (response) {
return callback("Não foi possível terminar upload do ficheiro: " + response);
});
}, req);
}