UNPKG

alphascript-server

Version:

CRUD operations for mongo and other functionalities to get started quickly in any CMS project

391 lines (328 loc) 14.1 kB
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 }, { 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); }