UNPKG

catalogue

Version:
239 lines (189 loc) 6.33 kB
/*jshint curly:false */ /*jshint evil:true */ var async = require('async'), flat = require('flat'), mongoose = require('mongoose'); //--------------------------------------------------- // Fetch Models //--------------------------------------------------- exports.models = function (req, res, next) { var modelNames = req.db.modelNames(); return res.json(modelNames); }; //--------------------------------------------------- // Fetch Documents //--------------------------------------------------- exports.getDoc = function (req, res, next) { var model = req.db.model( req.params.model ); var schema = model.schema; var fields = []; schema.eachPath(function(path, type) { if( path === '__v' ) return; fields.push( path ); }); model .findById(req.params.id) .select(fields.join(' ')) .lean() .exec(function(err, doc) { if( err ) return next( err ); if( ! doc ) return next( new Error('Document not found') ); res.json(doc); } ); }; exports.getDocs = function (req, res, next) { var model = req.db.model( req.params.model ); var schema = model.schema; var filter = req.query.filter ? decodeURIComponent(req.query.filter) : {}; var select = req.query.select ? decodeURIComponent(req.query.select) : undefined; var sort = req.query.sort ? decodeURIComponent(req.query.sort) : { $natural: -1 }; var populate = req.query.populate ? decodeURIComponent(req.query.populate) : {}; var skip = parseInt(decodeURIComponent(req.query.skip)); skip = ( !isNaN(skip) ) ? skip : 0; var limit = parseInt(decodeURIComponent(req.query.limit)); limit = ( !isNaN(limit) ) ? limit : 50; // Filter if( typeof filter === 'string' ) { try { filter = eval('(' + filter + ')'); } catch(e) { return next(e); } } // Population if( typeof populate === 'string' ) { try { populate = eval('(' + populate + ')'); } catch(e) { return next(e); } } // Selection criteria var fields; if( select ) { fields = select.split(' '); if( fields.indexOf('_id') === -1 ) fields.unshift('_id'); } else { fields = ['_id']; } var fieldData = [{ name : '_id', type : 'ObjectId', ref : req.params.model }]; schema.eachPath(function(path, type) { if( req.query.select && fields.indexOf( path ) == -1 ) return; if( path === '__v' ) return; if( path === '_id' ) return; if( Array.isArray( type.options.type ) ) return; // Warning: This relies on internals and could break in the future if( typeof type.options.type === 'function' ) { var name = type.options.type.name; if( /Mixed/i.test(name) ) return; } var field = { name: path }; // Warning: This relies on internals and could break in the future if( type.instance == 'ObjectID' ) { field.type = 'ObjectId'; field.ref = type.options.ref; } // Warning: This relies on internals and could break in the future if( /Date/.test(type.options.type.name) ) { field.type = 'Date'; } if( ! req.query.select ) fields.push( path ); fieldData.push( field ); }); // Mongoose Queries var documentsQuery = model.find(filter).select(select).lean().limit(limit).sort(sort).skip(skip); var countQuery = model.count(filter); var operations = { documents : function(cb) { for( var k in populate ) { if( populate.hasOwnProperty(k) ) { for ( var f = 0; f < fieldData.length; f++ ) { if( fieldData[f].name == k ) { fieldData[f].populated = true; break; } } documentsQuery.populate( k, populate[k] ); } } documentsQuery.exec(cb); }, count : function(cb) { countQuery.exec(cb); } }; async.parallel(operations, function(err, results) { if( err ) return next( err ); if( ! results.documents ) { results.documents = []; results.total = 0; } res.json({ fields: fieldData, documents: results.documents, total: results.count }); }); }; //--------------------------------------------------- // Add Document //--------------------------------------------------- exports.addDoc = function (req, res, next) { var model = req.db.model( req.params.model ); model.create(req.body.data, function(err, doc) { if( err ) return next( err ); return res.json( doc ); }); }; //--------------------------------------------------- // Update Document //--------------------------------------------------- exports.updateDoc = function (req, res, next) { var newDoc = req.body.data; var model = req.db.model( req.params.model ); var schema = model.schema; var keys = []; schema.eachPath(function(path, type) { keys.push( path ); }); model.findById(req.params.id, function(err, origDoc) { if( err ) return next( err ); if( ! origDoc ) return next( new Error('Document not found') ); newDoc = flat.flatten( newDoc, { safe: true } ); for( var key in newDoc ) { if( newDoc.hasOwnProperty(key) ) { origDoc.set(key, newDoc[key]); var keyIndex = keys.indexOf( key ); keys.splice( keyIndex, 1 ); } } for( var i = 0; i < keys.length; i++ ) { origDoc.set(keys[i], undefined); } origDoc.save(function(err) { if( err ) return next( err ); res.send( 200 ); }); }); }; //--------------------------------------------------- // Delete Document //--------------------------------------------------- exports.deleteDoc = function (req, res, next) { var model = req.db.model( req.params.model ); model.findById(req.params.id, function(err, doc) { if( err ) return next( err ); if( ! doc ) return next( new Error('Document not found') ); doc.remove(function(err) { if( err ) return next( err ); return res.send( 200, doc._id ); }); }); };