BVB Source Codes

mongo-express Show collection.js Source code

Return Download mongo-express: download collection.js Source code - Download mongo-express Source code - Type:.js
  1. 'use strict';
  2.  
  3. var _     = require('lodash');
  4. var bson  = require('../bson');
  5. var os    = require('os');
  6. var utils = require('../utils');
  7. var csv   = require('../csv');
  8.  
  9. const buildCollectionURL = utils.buildCollectionURL;
  10.  
  11. var routes = function (config) {
  12.   var exp = {};
  13.  
  14.   function validateCollectionName(name) {
  15.     if (name === undefined || name.length === 0) {
  16.       return { error: true, message: 'You forgot to enter a collection name!' };
  17.     }
  18.  
  19.     // Collection names must begin with a letter, underscore or slash, (tested v3.2.4)
  20.     // and can contain only letters, underscores, numbers, dots or slashes
  21.     if (!name.match(/^[a-zA-Z_/][a-zA-Z0-9._/]*$/)) {
  22.       return { error: true, message: 'That collection name is invalid.' };
  23.     }
  24.     return { error: false };
  25.   }
  26.  
  27.   /*
  28.    * Builds the Mongo query corresponding to the
  29.    * Simple/Advanced parameters input.
  30.    * Returns null if no query parameters were passed in request.
  31.    */
  32.   exp._buildMongoQuery = function (req) {
  33.     var result = null;
  34.     var key = req.query.key;
  35.     var value = req.query.value;
  36.     var type = req.query.type && req.query.type.toUpperCase();
  37.     var jsonQuery = req.query.query;
  38.  
  39.     if (key && value) {
  40.       // if it is a simple query,
  41.  
  42.       // 1. fist convert value to its actual type
  43.       var converters = {
  44.         // If type == J, convert value as json document
  45.         J: function (value) {
  46.           return JSON.parse(value);
  47.         },
  48.         // If type == N, convert value to number
  49.         N: function (value) {
  50.           return Number(value);
  51.         },
  52.         // If type == O, convert value to ObjectID
  53.         O: function (value) {
  54.           // Hex input
  55.           var result = bson.hexToObjectId(value);
  56.  
  57.           if (!result) {
  58.             // Basic validation
  59.             // Check we have ObjectID() wrapper
  60.             if (
  61.               value.toUpperCase().indexOf('OBJECTID(') === -1 ||   // missing the opening 'ObjectID('
  62.               value.indexOf(')') === -1                            // missing the closing '('
  63.             ) {
  64.               throw new Error('ObjectID(...) wrapper must be present');
  65.               // req.session.error = 'ObjectID(...) wrapper must be present';
  66.               // return res.redirect('back');
  67.             }
  68.  
  69.             result = bson.toObjectId(value);
  70.             if (!value) {
  71.               throw new Error('ObjectID is invalid');
  72.             }
  73.           }
  74.           return result;
  75.         },
  76.         // If type == R, convert to RegExp
  77.         R: function (value) {
  78.           return new RegExp(value, 'i');
  79.         },
  80.         // if type == S, no conversion done
  81.         S: function (value) {
  82.           return value;
  83.         },
  84.       };
  85.       if (!converters[type]) {
  86.         throw new Error('Invalid query type: ' + type);
  87.       }
  88.       value = converters[type](value);
  89.  
  90.       // 2. then set query to it
  91.       result = {};
  92.       result[key] = value;
  93.     } else if (jsonQuery) {
  94.       // if it is a complex query, take it as is;
  95.       result = bson.toSafeBSON(jsonQuery);
  96.       if (result === null) {
  97.         throw new Error('Query entered is not valid');
  98.       }
  99.     }
  100.     // otherwise leave as null;
  101.     return result;
  102.   };
  103.  
  104.   //view all entries in a collection
  105.   exp.viewCollection = function (req, res) {
  106.  
  107.     req.query = req.query || {}; // might not be present in Express5
  108.  
  109.     var limit = config.options.documentsPerPage;
  110.     var skip = parseInt(req.query.skip, 10) || 0;
  111.     var sort = req.query.sort || {};
  112.  
  113.     for (var i in sort) {
  114.       sort[i] = parseInt(sort[i], 10);
  115.     }
  116.  
  117.     var query_options = {
  118.       sort:   sort,
  119.       limit:  limit,
  120.       skip:   skip,
  121.     };
  122.  
  123.     var query;
  124.     try {
  125.       // if no criteria were passed, return whole list
  126.       query = exp._buildMongoQuery(req, res) || {};
  127.     } catch (err) {
  128.       req.session.error = err.message;
  129.       return res.redirect('back');
  130.     }
  131.  
  132.     var projection      = {};
  133.     var jsonProjection  = req.query.projection  || '';
  134.     if (jsonProjection) {
  135.       projection = bson.toSafeBSON(jsonProjection) || {};
  136.     }
  137.  
  138.     // determine default key
  139.     var dbName          = req.params.database;
  140.     var collectionName  = req.params.collection;
  141.     var defaultKey = (config.defaultKeyNames && config.defaultKeyNames[dbName] && config.defaultKeyNames[dbName][collectionName]) ?
  142.       config.defaultKeyNames[dbName][collectionName] :
  143.       '_id';
  144.     var edKey = function (doc, defaultKey) {
  145.       var defaultKeyAsArray = defaultKey.split('.');
  146.       var val = doc;
  147.       for (var i = 0; i < defaultKeyAsArray.length; i++) {
  148.         if (val[defaultKeyAsArray[i]]) {
  149.           val = val[defaultKeyAsArray[i]];
  150.         }
  151.       }
  152.       return val;
  153.     };
  154.  
  155.     req.collection.find(query, projection, query_options).toArray(function (err, items) {
  156.       req.collection.stats(function (err, stats) {
  157.         req.collection.indexes(function (err, indexes) {
  158.           req.collection.count(query, null, function (err, count) {
  159.             //Pagination
  160.             //Have to do this here, swig template doesn't allow any calculations :(
  161.             var prev;
  162.             var prev2;
  163.             var here;
  164.             var next2;
  165.             var next;
  166.             var last;
  167.             var pagination;
  168.  
  169.             prev = {
  170.               page: Math.round((skip - limit) / limit) + 1,
  171.               skip: skip - limit,
  172.             };
  173.             prev2 = {
  174.               page: Math.round((skip - limit * 2) / limit) + 1,
  175.               skip: skip - limit * 2,
  176.             };
  177.             next2 = {
  178.               page: Math.round((skip + limit * 2) / limit) + 1,
  179.               skip: skip + limit * 2,
  180.             };
  181.             next = {
  182.               page: Math.round((skip + limit) / limit) + 1,
  183.               skip: skip + limit,
  184.             };
  185.             here = Math.round(skip / limit) + 1;
  186.             last = (Math.ceil(count / limit) - 1) * limit;
  187.             pagination = count > limit;
  188.  
  189.             var docs    = [];
  190.             var columns = [];
  191.  
  192.             for (var i in items) {
  193.  
  194.               // Prep items with stubs so as not to send large info down the wire
  195.               for (let prop in items[i]) {
  196.                 if (utils.roughSizeOfObject(items[i][prop]) > config.options.maxPropSize) {
  197.                   items[i][prop] = {
  198.                     attribu: prop,
  199.                     display: '*** LARGE PROPERTY ***',
  200.                     humanSz: utils.bytesToSize(utils.roughSizeOfObject(items[i][prop])),
  201.                     maxSize: utils.bytesToSize(config.options.maxPropSize),
  202.                     preview: JSON.stringify(items[i][prop]).substr(0, 25),
  203.                     roughSz: utils.roughSizeOfObject(items[i][prop]),
  204.                     _id: items[i]._id,
  205.                   };
  206.                 }
  207.               }
  208.  
  209.               // If after prepping the row is still too big
  210.               if (utils.roughSizeOfObject(items[i]) > config.options.maxRowSize) {
  211.                 for (let prop in items[i]) {
  212.                   if (prop !== '_id' && utils.roughSizeOfObject(items[i][prop]) > 200) {
  213.                     items[i][prop] = {
  214.                       attribu: prop,
  215.                       display: '*** LARGE ROW ***',
  216.                       humanSz: utils.bytesToSize(utils.roughSizeOfObject(items[i][prop])),
  217.                       maxSize: utils.bytesToSize(config.options.maxRowSize),
  218.                       preview: JSON.stringify(items[i][prop]).substr(0, 25),
  219.                       roughSz: utils.roughSizeOfObject(items[i][prop]),
  220.                       _id: items[i]._id,
  221.                     };
  222.                   }
  223.                 }
  224.               }
  225.  
  226.               docs[i] = items[i];
  227.               columns.push(Object.keys(items[i]));
  228.               items[i] = bson.toString(items[i]);
  229.             }
  230.  
  231.             var indexSizes = stats.indexSizes;
  232.             for (var n = 0, nn = indexes.length; n < nn; n++) {
  233.               indexes[n].size = indexSizes[indexes[n].name];
  234.             }
  235.  
  236.  
  237.             // Generate an array of columns used by all documents visible on this page
  238.             columns = _.uniq(_.flatten(columns));
  239.  
  240.             var ctx = {
  241.               title: 'Viewing Collection: ' + req.collectionName,
  242.               documents: items, // Docs converted to strings
  243.               docs: docs,       // Original docs
  244.               columns: columns, // All used columns
  245.               count: count, // total number of docs returned by the query
  246.               stats: stats,
  247.               editorTheme: config.options.editorTheme,
  248.               limit: limit,
  249.               skip: skip,
  250.               sort: sort,
  251.               prev: prev,
  252.               prev2: prev2,
  253.               next2: next2,
  254.               next: next,
  255.               here: here,
  256.               last: last,
  257.               pagination: pagination,
  258.               key: req.query.key,
  259.               value: req.query.value,
  260.               // value: type === 'O' ? ['ObjectID("', value, '")'].join('') : value,
  261.               type: req.query.type,
  262.               query: req.query.query,
  263.               projection: jsonProjection,
  264.               defaultKey: defaultKey,
  265.               edKey: edKey,
  266.               collapsibleJSON: config.options.collapsibleJSON,
  267.               collapsibleJSONDefaultUnfold: config.options.collapsibleJSONDefaultUnfold,
  268.               indexes: indexes,
  269.             };
  270.  
  271.             res.render('collection', ctx);
  272.           });
  273.         });
  274.       });
  275.     });
  276.   };
  277.  
  278.   exp.compactCollection = function (req, res) {
  279.     req.db.command({ compact: req.collectionName }, function (err) {
  280.       if (err) {
  281.         req.session.error = 'Error: ' + err;
  282.         return res.redirect('back');
  283.       }
  284.  
  285.       req.session.success = 'Collection compacted!';
  286.       return res.redirect('back');
  287.     });
  288.   };
  289.  
  290.   exp.exportCollection = function (req, res) {
  291.     req.collection.find().toArray(function (err, items) {
  292.       res.setHeader('Content-disposition', 'attachment; filename=' + req.collectionName + '.json');
  293.       res.setHeader('Content-type', 'application/json');
  294.       var aItems = [];
  295.       for (var i in items) {
  296.         var docStr = bson.toJsonString(items[i]);
  297.         aItems.push(docStr);
  298.       }
  299.  
  300.       res.write(aItems.join(os.EOL));
  301.       res.end();
  302.     });
  303.   };
  304.  
  305.   exp.exportColArray = function (req, res) {
  306.     req.collection.find().toArray(function (err, items) {
  307.       res.setHeader('Content-disposition', 'attachment; filename=' + req.collectionName + '.json');
  308.       res.setHeader('Content-type', 'application/json');
  309.       res.write(bson.toJsonString(items));
  310.       res.end();
  311.     });
  312.   };
  313.  
  314.   exp.exportCsv = function (req, res) {
  315.     req.collection.find().toArray(function (err, items) {
  316.       res.setHeader('Content-disposition', 'attachment; filename=' + req.collectionName + '.csv');
  317.       res.setHeader('Content-type', 'application/json');
  318.       res.write(csv(items));
  319.       res.end();
  320.     });
  321.   };
  322.  
  323.   exp.reIndex = function (req, res) {
  324.     req.collection.reIndex(function (err) {
  325.       if (err) {
  326.         req.session.error = 'Error: ' + err;
  327.         return res.redirect('back');
  328.       }
  329.  
  330.       req.session.success = 'Index regenerated!';
  331.       return res.redirect('back');
  332.     });
  333.   };
  334.  
  335.   exp.addCollection = function (req, res) {
  336.     var name = req.body.collection;
  337.  
  338.     const validation = validateCollectionName(name);
  339.     if (validation.error) {
  340.       req.session.error = validation.message;
  341.       return res.redirect('back');
  342.     }
  343.  
  344.     req.db.createCollection(name, function (err) {
  345.       if (err) {
  346.         req.session.error = 'Something went wrong: ' + err;
  347.         console.error(err);
  348.         return res.redirect('back');
  349.       }
  350.  
  351.       req.updateCollections(req.db, req.dbName, function () {
  352.         req.session.success = 'Collection created!';
  353.         res.redirect(buildCollectionURL(res.locals.baseHref, req.dbName, name));
  354.       });
  355.     });
  356.   };
  357.  
  358.   exp.deleteCollection = function (req, res) {
  359.     if (config.options.readOnly === true) {
  360.       req.session.error = 'Error: config.options.readOnly is set to true';
  361.       return res.redirect('back');
  362.     }
  363.     var query = exp._buildMongoQuery(req);
  364.     if (query) {
  365.       // we're just deleting some of the documents
  366.       var deleteOptions = null;
  367.       req.collection.deleteMany(query, deleteOptions, function (err, opRes) {
  368.         if (err) {
  369.           req.session.error = 'Something went wrong: ' + err;
  370.           console.error(err);
  371.           return res.redirect('back');
  372.         }
  373.         req.session.success = opRes.result.n + ' documents deleted from "' + req.collectionName + '"';
  374.         res.redirect(res.locals.baseHref + 'db/' + req.dbName + '/' + req.collectionName);
  375.       });
  376.     } else {
  377.       // no query means we're dropping the whole collection
  378.       req.collection.drop(function (err) {
  379.         if (err) {
  380.           req.session.error = 'Something went wrong: ' + err;
  381.           console.error(err);
  382.           return res.redirect('back');
  383.         }
  384.         req.updateCollections(req.db, req.dbName, function (err) {
  385.           if (err) {
  386.             req.session.error = 'Something went wrong: ' + err;
  387.             console.error(err);
  388.             return res.redirect('back');
  389.           }
  390.           req.session.success = 'Collection  "' + req.collectionName + '" deleted!';
  391.           res.redirect(res.locals.baseHref + 'db/' + req.dbName);
  392.         });
  393.       });
  394.     }
  395.   };
  396.  
  397.   exp.renameCollection = function (req, res) {
  398.     var name = req.body.collection;
  399.  
  400.     const validation = validateCollectionName(name);
  401.     if (validation.error) {
  402.       req.session.error = validation.message;
  403.       return res.redirect('back');
  404.     }
  405.  
  406.     req.collection.rename(name, function (err) {
  407.       if (err) {
  408.         req.session.error = 'Something went wrong: ' + err;
  409.         console.error(err);
  410.         return res.redirect('back');
  411.       }
  412.  
  413.       req.updateCollections(req.db, req.dbName, function (err) {
  414.         if (err) {
  415.           req.session.error = 'Something went wrong: ' + err;
  416.           return res.redirect('back');
  417.         }
  418.  
  419.         req.session.success = 'Collection renamed!';
  420.         res.redirect(buildCollectionURL(res.locals.baseHref, req.dbName, name));
  421.       });
  422.     });
  423.   };
  424.  
  425.   exp.updateCollections = function (req, res) {
  426.     req.updateCollections(req.db, req.dbName, function (err) {
  427.       if (err) {
  428.         req.session.error = 'Something went wrong: ' + err;
  429.         return res.redirect('back');
  430.       }
  431.  
  432.       req.session.success = 'Collections Updated!';
  433.       res.redirect(res.locals.baseHref + 'db/' + req.dbName);
  434.     });
  435.   };
  436.  
  437.   exp.dropIndex = function (req, res) {
  438.     if (!req.query.name) {
  439.       req.session.error = 'Error: missing name parameter';
  440.       return res.redirect('back');
  441.     }
  442.     if (config.options.readOnly === true) {
  443.       req.session.error = 'Error: config.options.readOnly is set to true';
  444.       return res.redirect('back');
  445.     }
  446.     req.collection.dropIndex(req.query.name, function (err) {
  447.       if (err) {
  448.         req.session.error = 'Error: ' + err;
  449.         return res.redirect('back');
  450.       }
  451.  
  452.       req.session.success = 'Index deleted!';
  453.       return res.redirect('back');
  454.     });
  455.   };
  456.  
  457.   return exp;
  458. };
  459.  
  460. module.exports = routes;
  461.  
downloadcollection.js Source code - Download mongo-express Source code
Related Source Codes/Software:
XCL-Charts - Android charting libraries (XCL-Charts is a free c... 2017-05-17
scrollMonitor - A simple and fast API to monitor elements as you s... 2017-05-16
XCDYouTubeKit - YouTube video player for iOS, tvOS and macOS 2017-05-16
rails-erd - Generate Entity-Relationship Diagrams for Rails ap... 2017-05-16
np - A better `npm publish` 2017-05-16
kaminari - A Scope & Engine based, clean, powerful, custo... 2017-06-04
python-fire - Python Fire is a library for automatically generat... 2017-06-04
Dapper - Dapper - a simple object mapper for .Net 2017-06-05
pkg - Package your Node.js project into an executable ... 2017-06-05
packer - Packer is a tool for creating identical machine im... 2017-06-05
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top