restful-goose
Advanced tools
Comparing version 2.2.22 to 2.2.23
@@ -6,4 +6,3 @@ var express = require('express'); | ||
var bodyParser = require('body-parser'); | ||
var morgan = require('morgan'); | ||
var debug = require('debug')('restful-goose:app'); | ||
var winston = require('winston'); | ||
var errorDefs = require('./errors'); | ||
@@ -17,5 +16,6 @@ | ||
* @typedef {Object} RGOptions | ||
* @property {string | boolean} prefix - Provide a path prefix to preface all constructed links with (ex: /api). If set to `true`, will construct links automatically. Set to `false` to only build partial links. | ||
* @property {string|boolean} prefix - Provide a path prefix to preface all constructed links with (ex: /api). If set to `true`, will construct links automatically. Set to `false` to only build partial links. | ||
* @property {mongoose.Model[]} models - Models to enable on the API. If none are provided, all models registered to the passed in mongoose connection will be used (the default option). This will be overriden if `RestfulGoose.defineRoute()` is called on a model after initialization. | ||
* | ||
* @property {winston.Logger} log - Pass in your log service to use for logging. Accepts any thing object that has methods for info, log, error, debug, etc. Defaults to winston's global logger instance. | ||
* @property {boolean} suppress4xxErrors - Prevents 400 level errors from being printed in the error log (they will be printed to info instead). Defaults to true. | ||
*/ | ||
@@ -37,5 +37,8 @@ | ||
var routeMap = {}; | ||
var log; | ||
var defaultOpts = { | ||
prefix: false, | ||
models: mongoose.models | ||
models: mongoose.models, | ||
log: winston, | ||
suppress4xxErrors: true | ||
}; | ||
@@ -48,6 +51,7 @@ | ||
_.defaults(options, defaultOpts); | ||
log = options.log; | ||
debug(_.size(mongoose.models) + ' models registered to mongoose instance.'); | ||
log.debug('%s models registered to mongoose instance.', _.size(options.models)); | ||
_.forEach(options.models, function(model) { | ||
debug('Generating default route map for ' + model.modelName); | ||
log.debug('Generating default route map for ' + model.modelName); | ||
_.set(routeMap, model.modelName, RouteMap.extend({})); | ||
@@ -62,3 +66,3 @@ }); | ||
api.all('*', function(req, res, next) { | ||
debug('Setting rg response variables...'); | ||
log.debug('Setting rg response variables...'); | ||
_.set(res, 'rg.mongoose', mongoose); | ||
@@ -68,4 +72,6 @@ _.set(res, 'rg.routeMap', routeMap); | ||
_.set(res, 'rg.prefix', options.prefix); | ||
debug('res.rg.mongoose: ' + Boolean(res.rg.mongoose)); | ||
debug('res.rg.routeMap: ' + Boolean(res.rg.routeMap)); | ||
_.set(res, 'rg.log', options.log); | ||
_.set(res, 'rg.supress4xxErrors', options.suppress4xxErrors); | ||
log.debug('res.rg.mongoose: ' + Boolean(res.rg.mongoose)); | ||
log.debug('res.rg.routeMap: ' + Boolean(res.rg.routeMap)); | ||
next(); | ||
@@ -83,7 +89,7 @@ }); | ||
api.defineRoute = function(modelName, modelRouteMap) { | ||
debug('api.defineRoute invoked for ' + modelName); | ||
log.debug('api.defineRoute invoked for ' + modelName); | ||
_.set(routeMap, modelName, modelRouteMap); | ||
}; | ||
debug('Mounting router to api object...'); | ||
log.debug('Mounting router to api object...'); | ||
api.use(router); | ||
@@ -90,0 +96,0 @@ |
var crypto = require('crypto'); | ||
var _ = require('lodash'); | ||
var debug = require('debug')('restful-goose:error-handler'); | ||
@@ -13,2 +12,3 @@ /** | ||
var err = res.errors[0]; | ||
var log = res.rg.log; | ||
function getErrCode(errName) { | ||
@@ -40,3 +40,3 @@ switch (errName) { | ||
function toJSONErrorObject(error, key) { | ||
function toJSONErrorObject(error) { | ||
function extractPathFromErrorMessage(mesg) { | ||
@@ -96,8 +96,11 @@ var r = /(?:\$|_)?(?:([a-z]+)_[0-9]_?)+/i; | ||
var suppress = res.rg.suppress4xxErrors; | ||
var errorsArray = _.flatten(res.errors); | ||
var errStatus = getErrCode(err.name); | ||
var logError = function(err) { | ||
var level = !!suppress && (errStatus >= 400 || errStatus <= 499) ? 'info' : 'error'; | ||
log[level](err.name + '\n' + err.message + '\n' + err.stack); | ||
}; | ||
debug(res.errors); | ||
debug(err.name); | ||
res.errors.forEach(logError); | ||
res.status(errStatus); | ||
@@ -104,0 +107,0 @@ errorsArray = err.name === 'ValidationError' ? _.toArray(_.mapValues(err.errors, parseValidationErrors)) : _.map(errorsArray, toJSONErrorObject); |
var _ = require('lodash'); | ||
var RGError = function(msg, name, code) { | ||
'use strict'; | ||
this.name = name; | ||
@@ -31,2 +32,3 @@ this.message = msg; | ||
_.forEach(ERRDEFS, function(def, key) { | ||
'use strict'; | ||
ERR[key] = function(message) { | ||
@@ -33,0 +35,0 @@ if (def.message) { |
@@ -5,3 +5,2 @@ var helpers = require('./helpers'); | ||
var _ = require('lodash'); | ||
var debug = require('debug')('restful-goose:RouteMap'); | ||
var mongoose = require('mongoose'); | ||
@@ -73,3 +72,3 @@ | ||
if (req.method === METHODS.PATCH) { | ||
debug(req.body); | ||
res.rg.log.debug(req.body); | ||
} | ||
@@ -98,3 +97,3 @@ | ||
if (req.method === METHODS.PATCH) { | ||
debug(req.data); | ||
res.rg.log.debug(req.data); | ||
} | ||
@@ -106,6 +105,6 @@ return next(); | ||
RouteMap.prototype.findOne = function(req, res, next) { | ||
debug('findOne() invoked'); | ||
res.rg.log.debug('findOne() invoked'); | ||
if (!mongoose.Types.ObjectId.isValid(req.params.item_id)) { | ||
debug(`NotFound pushed to errors stack because ${req.params.item_id} is not a valid MongoDB ID`); | ||
res.rg.log.debug('NotFound pushed to errors stack because %s is not a valid MongoDB ID', req.params.item_id); | ||
res.errors.push(res.rg.ERR.NOT_FOUND()); | ||
@@ -116,3 +115,3 @@ return next(); | ||
if (err) { res.errors.push(err); } | ||
if (!item) { res.errors.push(res.rg.ERR.NOT_FOUND()); debug('NotFound pushed to errors stack'); } | ||
if (!item) { res.errors.push(res.rg.ERR.NOT_FOUND()); res.rg.log.debug('NotFound pushed to errors stack'); } | ||
if (err || !item) { | ||
@@ -122,3 +121,3 @@ return next(); | ||
res.model = item; | ||
debug(res.model._id); | ||
res.rg.log.debug(res.model._id); | ||
next(); | ||
@@ -132,3 +131,3 @@ }); | ||
var relationshipPath = _.camelCase(req.params.relationship_type); | ||
debug('findRelationship() invoked'); | ||
res.rg.log.debug('findRelationship() invoked'); | ||
@@ -144,6 +143,6 @@ parentModelName = helpers.toModelName(req.params.resource_type); | ||
if (req.method === METHODS.GET) { | ||
debug(req.params.relationship_type); | ||
debug(relationshipPath); | ||
debug(parentItem[relationshipPath]); | ||
debug(req.params.item_id); | ||
res.rg.log.debug(req.params.relationship_type); | ||
res.rg.log.debug(relationshipPath); | ||
res.rg.log.debug(parentItem[relationshipPath]); | ||
res.rg.log.debug(req.params.item_id); | ||
} | ||
@@ -160,3 +159,3 @@ | ||
RouteMap.prototype.find = function(req, res, next) { | ||
debug('find() invoked'); | ||
res.rg.log.debug('find() invoked'); | ||
helpers.querySearch(req, res, function(err, results) { | ||
@@ -181,11 +180,11 @@ if(err) { res.errors.push(err); } | ||
if (req.params.relationship_type) { | ||
debug('Get relationship'); | ||
res.rg.log.debug('Get relationship'); | ||
res.hasParent = true; | ||
_this.findRelationship(req, res, next); | ||
} else if (req.params.item_id && req.method !== METHODS.POST) { | ||
debug('Get one'); | ||
res.rg.log.debug('Get one'); | ||
res.hasParent = false; | ||
_this.findOne(req, res, next); | ||
} else if (req.method !== METHODS.POST) { | ||
debug('Get many'); | ||
res.rg.log.debug('Get many'); | ||
res.hasParent = false; | ||
@@ -225,3 +224,3 @@ _this.find(req, res, next); | ||
function _createRelationship(done) { | ||
debug('Adding new relationship invoked'); | ||
res.rg.log.debug('Adding new relationship invoked'); | ||
@@ -233,3 +232,3 @@ var update = Array.isArray(req.data) ? req.data : [req.data.id]; | ||
if (Array.isArray(res.parentModel[pathName])) { | ||
debug('isArray'); | ||
res.rg.log.debug('isArray'); | ||
res.parentModel[pathName] = _.chain(existingIds).concat(update).uniq().value(); | ||
@@ -249,4 +248,4 @@ } else { | ||
if (req.data) { | ||
debug('Create item invoked'); | ||
debug(req.data); | ||
res.rg.log.debug('Create item invoked'); | ||
res.rg.log.debug(req.data); | ||
res.rg.Model.create(req.data, function(err, doc) { | ||
@@ -283,4 +282,4 @@ if (err) { res.errors.push(err); } | ||
function _updateRelationship(done) { | ||
debug('Update relationship invoked'); | ||
debug(req.data); | ||
res.rg.log.debug('Update relationship invoked'); | ||
res.rg.log.debug(req.data); | ||
var data = Array.isArray(req.data) ? req.data : req.data.id; | ||
@@ -297,3 +296,3 @@ res.parentModel[res.relationshipPath] = data; | ||
function _updateItem(done) { | ||
debug('Update item invoked'); | ||
res.rg.log.debug('Update item invoked'); | ||
_.forEach(req.data, function(value, path) { | ||
@@ -352,3 +351,3 @@ res.model[path] = value; | ||
function _deleteItem(done) { | ||
debug('Delete item invoked'); | ||
res.rg.log.debug('Delete item invoked'); | ||
res.model.remove(function (err) { | ||
@@ -431,3 +430,3 @@ if (err) { | ||
debug('Pulling ' + includes.length + ' includes from the db...'); | ||
res.rg.log.debug('Pulling ' + includes.length + ' includes from the db...'); | ||
async.each(includes, function(include, done) { | ||
@@ -476,3 +475,3 @@ var includeArray; | ||
if (err) { | ||
debug(err); | ||
res.rg.log.debug(err); | ||
return callback(err); | ||
@@ -482,3 +481,3 @@ } | ||
res.included = _.chain(res.included).uniq().compact().value(); | ||
debug('Populated ' + res.included.length + ' documents from include'); | ||
res.rg.log.debug('Populated ' + res.included.length + ' documents from include'); | ||
callback(); | ||
@@ -495,3 +494,3 @@ }); | ||
debug('Includes found: ' + req.query.include); | ||
res.rg.log.debug('Includes found: ' + req.query.include); | ||
@@ -498,0 +497,0 @@ if (Array.isArray(res.model)) { |
var express = require('express'); | ||
var async = require('async'); | ||
var debug = require('debug')('restful-goose:router'); | ||
var moment = require('moment'); | ||
@@ -13,7 +12,6 @@ var _ = require('lodash'); | ||
var router = express.Router(); | ||
var paths = ['/:resource_type/:parent_item_id/relationships/:relationship_type/:item_id', '/:resource_type/:parent_item_id/relationships/:relationship_type', '/:resource_type/:item_id', '/:resource_type?']; | ||
debug('Router instantiated'); | ||
var paths = ['/:resource_type/:parent_item_id/relationships/:relationship_type/:item_id', '/:resource_type/:parent_item_id/relationships/:relationship_type', '/:resource_type/:item_id', '/:resource_type?']; | ||
router.use(paths, function(req, res) { | ||
debug('initialize request'); | ||
res.rg.log.debug('initialize request'); | ||
var startTime = Date.now(); | ||
@@ -26,8 +24,8 @@ var method = req.method; | ||
}); | ||
debug('Received ' + method + ' request at ' + req.originalUrl); | ||
debug('Event Queue: ' + _.keys(eventQueue).join(', ')); | ||
res.rg.log.debug('Received ' + method + ' request at ' + req.originalUrl); | ||
res.rg.log.debug('Event Queue: ' + _.keys(eventQueue).join(', ')); | ||
_.set(res, 'rg.currentMap', currentMap); | ||
async.eachOfSeries(eventQueue, function(fn, key, next) { | ||
debug('Route ' + req.originalUrl + ' event: ' + key); | ||
res.rg.log.debug('Route ' + req.originalUrl + ' event: ' + key); | ||
@@ -47,3 +45,3 @@ if (res.headersSent) { | ||
debug('Request completed in ' + processTime + ' milliseconds'); | ||
res.rg.log.debug('Request completed in ' + processTime + ' milliseconds'); | ||
}); | ||
@@ -50,0 +48,0 @@ }); |
{ | ||
"name": "restful-goose", | ||
"version": "2.2.22", | ||
"version": "2.2.23", | ||
"description": "A new improved version of your favorite API framework for mongoose/MongoDB", | ||
@@ -30,9 +30,9 @@ "main": "index.js", | ||
"dependencies": { | ||
"async": "2.0.1", | ||
"body-parser": "1.15.2", | ||
"express": "4.14.0", | ||
"lodash": "4.14.1", | ||
"moment": "2.14.1", | ||
"morgan": "1.7.0", | ||
"pluralize": "3.0.0" | ||
"async": "2.1.5", | ||
"body-parser": "1.16.1", | ||
"express": "4.14.1", | ||
"lodash": "4.17.4", | ||
"moment": "2.17.1", | ||
"pluralize": "3.0.0", | ||
"winston": "2.3.1" | ||
}, | ||
@@ -47,4 +47,4 @@ "devDependencies": { | ||
"mocha": "3.0.1", | ||
"mongoose": "4.5.8" | ||
"mongoose": "4.8.5" | ||
} | ||
} |
@@ -0,1 +1,2 @@ | ||
/* globals describe, before, after, it */ | ||
var assert = require('chai').assert; | ||
@@ -13,2 +14,3 @@ var faker = require('faker'); | ||
var connectDb = function(callback) { | ||
'use strict'; | ||
var connection = mongoose.connect(testDb); | ||
@@ -25,2 +27,3 @@ mongoose.connection.on('connected', function(err) { | ||
var createTestModel = function(callback) { | ||
'use strict'; | ||
var schema = new mongoose.Schema({ | ||
@@ -45,3 +48,3 @@ name: String, | ||
compoundschema.index({ name: 1, motto: 1 }, { unique: true }) | ||
compoundschema.index({ name: 1, motto: 1 }, { unique: true }); | ||
@@ -56,2 +59,3 @@ mongoose.model('CompoundTest', compoundschema); | ||
var createTestData = function(callback) { | ||
'use strict'; | ||
var SubModel = mongoose.model('SubTest'); | ||
@@ -76,2 +80,3 @@ var Model = mongoose.model('Test'); | ||
before(function(done) { | ||
'use strict'; | ||
async.series([connectDb, createTestModel, createTestData], done); | ||
@@ -81,2 +86,3 @@ }); | ||
after(function(done) { | ||
'use strict'; | ||
mongoose.connection.close(done); | ||
@@ -87,2 +93,3 @@ }); | ||
describe('constructor tests', function() { | ||
'use strict'; | ||
it('should create an app for the test model', function(done) { | ||
@@ -89,0 +96,0 @@ var app = restfulGoose(mongoose); |
/* globals describe, before, after, it */ | ||
var api = require('../index'); | ||
var mongoose = require('mongoose'); | ||
var winston = require('winston'); | ||
var connection; | ||
@@ -28,5 +29,15 @@ | ||
it ('should open the app without throwing an exception', function(done) { | ||
api(mongoose); | ||
api(connection); | ||
done(); | ||
}); | ||
it('should allow user to pass their own instance of winston in as an option', function(done) { | ||
var logger = new (winston.Logger)({ | ||
level: 'debug' | ||
}); | ||
api(connection, { | ||
log: logger | ||
}); | ||
done(); | ||
}); | ||
}); |
1110625
51
2671
+ Addedwinston@2.3.1
+ Addedasync@1.0.02.1.5(transitive)
+ Addedbody-parser@1.16.1(transitive)
+ Addedcolors@1.0.3(transitive)
+ Addedcontent-disposition@0.5.2(transitive)
+ Addedcycle@1.0.3(transitive)
+ Addeddebug@2.6.1(transitive)
+ Addedexpress@4.14.1(transitive)
+ Addedeyes@0.1.8(transitive)
+ Addedfinalhandler@0.5.1(transitive)
+ Addediconv-lite@0.4.15(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedlodash@4.17.4(transitive)
+ Addedmoment@2.17.1(transitive)
+ Addedqs@6.2.1(transitive)
+ Addedraw-body@2.2.0(transitive)
+ Addedstack-trace@0.0.10(transitive)
+ Addedwinston@2.3.1(transitive)
- Removedmorgan@1.7.0
- Removedasync@2.0.1(transitive)
- Removedbasic-auth@1.0.4(transitive)
- Removedbody-parser@1.15.2(transitive)
- Removedcontent-disposition@0.5.1(transitive)
- Removedexpress@4.14.0(transitive)
- Removedfinalhandler@0.5.0(transitive)
- Removediconv-lite@0.4.13(transitive)
- Removedlodash@4.14.1(transitive)
- Removedmoment@2.14.1(transitive)
- Removedmorgan@1.7.0(transitive)
- Removedon-headers@1.0.2(transitive)
- Removedraw-body@2.1.7(transitive)
- Removedsend@0.14.1(transitive)
Updatedasync@2.1.5
Updatedbody-parser@1.16.1
Updatedexpress@4.14.1
Updatedlodash@4.17.4
Updatedmoment@2.17.1