restful-goose
Advanced tools
Comparing version 2.0.3 to 2.0.4
@@ -1,1 +0,5 @@ | ||
module.exports = require('./lib/app'); | ||
/** | ||
* @module RestfulGoose | ||
* @description An express app that functions as a JSONAPI for Mongoose models | ||
*/ | ||
module.exports = require('./lib/app'); |
@@ -10,7 +10,3 @@ var express = require('express'); | ||
/** | ||
* @namespace RestfulGoose | ||
* @augments express.App | ||
* @description An express app that functions as a JSONAPI for Mongoose models | ||
*/ | ||
module.exports = (function() { | ||
@@ -24,5 +20,8 @@ 'use strict'; | ||
* @param {mongoose.Connection} mongoose - The Mongoose connection to use for all operations | ||
* @returns {RestfulGoose} A new Express App object that is ready to be mounted in your parent application | ||
* @returns {RestfulGooseApp} - A new Express App object that is ready to be mounted in your parent application | ||
*/ | ||
var RGFactory = function(mongoose) { | ||
/** | ||
* @var RestfulGooseApp | ||
*/ | ||
var api = express(); | ||
@@ -51,7 +50,7 @@ var routeMap = {}; | ||
}); | ||
/** | ||
* @method defineRoute | ||
* @public | ||
* @memberof RestfulGoose | ||
* @access public | ||
* @memberof RestfulGooseApp | ||
* @param {string} modelName - Name of the model to bind the route to | ||
@@ -73,10 +72,12 @@ * @param {RouteMap} modelRouteMap - A route map constructed with the extend() method | ||
/** | ||
* @public | ||
* @access public | ||
* @type {RouteMap} | ||
* @memberof RestfulGoose | ||
* @description Exposing the RouteMap object to the application | ||
*/ | ||
RGFactory.RouteMap = RouteMap; | ||
/** | ||
* @exports | ||
*/ | ||
return RGFactory; | ||
}()); | ||
}()); |
@@ -34,3 +34,3 @@ var _ = require('lodash'); | ||
} | ||
return { data: { type: toResourceType(modelName), id: id }, links: { self: '/' + toResourceType(modelName) + '/' + id }}; | ||
return { self: '/' + toResourceType(modelName) + '/' + id }; | ||
}; | ||
@@ -46,3 +46,3 @@ /** | ||
}).mapValues(function(v) { | ||
if (typeof v === 'object' && !Array.isArray(v)) { | ||
if (typeof v === 'object' && v instanceof Date === false && _.isNull(v) === false && !Array.isArray(v)) { | ||
return keysToKebab(v); | ||
@@ -78,2 +78,6 @@ } else { | ||
debug('serializer invoked'); | ||
if(!doc) { | ||
return; | ||
} | ||
debug(doc.toObject ? doc.toObject() : ''); | ||
if (Array.isArray(doc)) { | ||
@@ -84,2 +88,3 @@ return _.map(doc, serialize); | ||
var omitted = [ 'id' ]; | ||
Model.schema.eachPath(function(pathName) { | ||
@@ -97,18 +102,21 @@ if (_.startsWith(pathName, '_')) { | ||
var serialized = { type: toResourceType(Model.modelName), id: doc._id.toString() }; | ||
var raw = _.omit(doc.toObject(), omitted); | ||
var raw = doc.toObject(); | ||
raw = _.omit(raw, omitted); | ||
_.assign(serialized, { attributes: raw }); | ||
serialized.attributes = raw; | ||
_.forEach(relationships, function (rel) { | ||
if (doc[rel.path] && Array.isArray(doc[rel.path]) && doc[rel.path].length) { | ||
_.set(serialized, 'relationships.' + rel.path, _.map(doc[rel.path], function(id) { | ||
return toLinkObject(rel.ref, id); | ||
})); | ||
var relationship = { links: { self: '/' + serialized.type + '/' + doc.id + '/relationships/' + toResourceType(rel.ref) }}; | ||
relationship.data = _.map(doc[rel.path], function(id) { | ||
return { type: toResourceType(rel.ref), id: id.toString() }; | ||
}); | ||
_.set(serialized, 'relationships.' + rel.path, relationship); | ||
} else if (doc[rel.path] && !Array.isArray(doc[rel.path])) { | ||
_.set(serialized, 'relationships.' + rel.path, toLinkObject(rel.ref, doc[rel.path])); | ||
_.set(serialized, 'relationships.' + rel.path, { data: { type: toResourceType(rel.ref), id: doc[rel.path].toString() }, links: toLinkObject(rel.ref, doc[rel.path]) }); | ||
} | ||
}); | ||
serialized.links = [toLinkObject(Model.modelName, doc._id)]; | ||
serialized.links[0].type = 'self'; | ||
serialized.links = toLinkObject(Model.modelName, doc._id); | ||
serialized.links.type = 'self'; | ||
@@ -131,3 +139,3 @@ return keysToKebab(serialized); | ||
_.forEach(o.relationships, function(value, modelPath) { | ||
relationships[modelPath] = Array.isArray(value) ? _.map(value, 'data.id') : value.data.id; | ||
relationships[modelPath] = value.data && Array.isArray(value.data) ? _.map(value.data, 'id') : value.data.id; | ||
}); | ||
@@ -134,0 +142,0 @@ |
@@ -9,3 +9,3 @@ var helpers = require('./helpers'); | ||
/** | ||
* @namespace RouteMap | ||
* @class RouteMap | ||
* @description Interfaces with a Mongoose model to handle API requests for a single object or a collection of objects | ||
@@ -24,7 +24,7 @@ */ | ||
RouteMap.prototype = Object.create(null); | ||
/** | ||
* Returns a fresh copy of RouteMap with your provided hash of functions. Use this to replace the default event handlers with your own. | ||
* @memberof RouteMap | ||
* @method extend | ||
* @method extend | ||
* @param {object} properties - A hash of functions with handlers for various events, called during invocation | ||
@@ -63,3 +63,3 @@ * @returns {RouteMap} routeMap - New route map | ||
sendError: ERR | ||
}); | ||
}); | ||
res.errors = []; | ||
@@ -90,3 +90,3 @@ | ||
RouteMap.prototype.beforeModel.methods = [METHODS.GET, METHODS.DELETE, METHODS.PATCH]; | ||
RouteMap.prototype.findOne = function(req, res, next) { | ||
@@ -112,3 +112,3 @@ debug('findOne() invoked'); | ||
RouteMap.prototype.findOne.methods = []; | ||
RouteMap.prototype.findParent = function(req, res, next) { | ||
@@ -122,3 +122,3 @@ var ParentModel, parentModelName; | ||
ParentModel.findById(req.params.parent_item_id, function(err, parentItem) { | ||
var reference = _.find(parentItem.constructor.schema.paths, function(path) { | ||
var reference = _.find(parentItem.constructor.schema.paths, function(path) { | ||
return path.options && path.options.ref === res.rg.Model.modelName; | ||
@@ -141,4 +141,4 @@ }); | ||
}; | ||
RouteMap.prototype.findParent.methods = []; | ||
RouteMap.prototype.findParent.methods = []; | ||
RouteMap.prototype.find = function(req, res, next) { | ||
@@ -153,5 +153,5 @@ debug('find() invoked'); | ||
RouteMap.prototype.find.methods = []; | ||
/** | ||
* Queries the database for a model. Called on GET, PATCH, and DELETE requests. Cannot be overwritten. | ||
* Queries the database for a model. Called on GET, PATCH, and DELETE requests. Cannot be overwritten. | ||
* @private | ||
@@ -167,7 +167,7 @@ * @param req | ||
} | ||
function _getParent(done) { | ||
_this.findParent(req, res, done); | ||
} | ||
if(req.params.parent_item_id && req.params.item_id) { | ||
@@ -182,3 +182,3 @@ async.series([_getItem, _getParent], next); | ||
} | ||
}; | ||
@@ -283,3 +283,3 @@ RouteMap.prototype.model.methods = [METHODS.GET, METHODS.PATCH, METHODS.DELETE]; | ||
/** | ||
* Middleware called after the model has been removed in a DELETE request. Can be overwritten with [RouteMap.extend()]{@link RouteMap.extend} | ||
* Middleware called after the model has been removed in a DELETE request. Can be overwritten with [RouteMap.extend()]{@link RouteMap.extend} | ||
* @public | ||
@@ -341,5 +341,5 @@ * @memberof RouteMap | ||
} | ||
res.data = { data: ((!Array.isArray(res.model) && typeof res.model === 'object') || (Array.isArray(res.model) && res.model.length)) ? helpers.serialize(res.model) : ((res.model === []) ? [] : null )}; | ||
if (Array.isArray(res.model) && req.pageNumber && !_.isNaN(req.pageNumber)) { | ||
@@ -356,3 +356,3 @@ basePageLink = '/' + helpers.toResourceType(res.rg.Model.modelName); | ||
} | ||
return next(); | ||
@@ -391,3 +391,3 @@ }; | ||
} | ||
return next(); | ||
@@ -397,6 +397,6 @@ }; | ||
RouteMap.prototype.sendResponse.isPrivate = true; | ||
return RouteMap; | ||
}()); | ||
module.exports = Object.create(RouteMap.prototype); | ||
module.exports = Object.create(RouteMap.prototype); |
{ | ||
"name": "restful-goose", | ||
"version": "2.0.3", | ||
"version": "2.0.4", | ||
"description": "A new improved version of your favorite API framework for mongoose/MongoDB", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -49,3 +49,3 @@ var helpers = require('../lib/helpers'); | ||
expect(pkg.attributes.rank).to.equal(o.rank); | ||
expect(pkg.relationships.subs[0].data.id).to.equal(sub._id.toString()); | ||
expect(pkg.relationships.subs.data[0].id).to.equal(sub._id.toString()); | ||
done(); | ||
@@ -55,2 +55,11 @@ }); | ||
}); | ||
it('should not convert embedded objects like createdAt and updatedAt into empty objects', function(done) { | ||
connection.model('RequestTest').findOne({}, {}, {}, function(err, doc) { | ||
var s = helpers.serialize(doc); | ||
//expect(Object.keys(doc.updatedAt).length).to.not.equal(0); | ||
expect(s.attributes['updated-at'] instanceof Date).to.equal(true); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
@@ -94,2 +103,26 @@ | ||
it('should properly deserialize an object with empty array for relationship', function(done) { | ||
connection.model('RequestTest').findOne({}, {}, {}, function(err, doc) { | ||
doc.subs = []; | ||
var s = helpers.serialize(doc); | ||
var d = helpers.deserialize(s); | ||
expect(d).to.be.a('object'); | ||
expect(d).not.have.property('subs'); | ||
done(); | ||
}); | ||
}); | ||
it('should properly deserialize an object with null for a relationship', function(done) { | ||
connection.model('SubTest').findOne({}, {}, {}, function(err, doc) { | ||
doc.parent = null; | ||
var s = helpers.serialize(doc); | ||
var d = helpers.deserialize(s); | ||
expect(d).to.be.a('object'); | ||
expect(d).not.have.property('parent'); | ||
done(); | ||
}); | ||
}); | ||
it('should properly deserialize an object with a one-to-one relationship', function(done) { | ||
@@ -96,0 +129,0 @@ connection.model('SubTest').findOne({ parent: { $exists: true }}, {}, {}, function(err, doc) { |
@@ -53,4 +53,4 @@ /* globals describe, before, after, it */ | ||
expect(item.relationships).to.have.property('subs'); | ||
expect(item.relationships.subs[0]).to.have.all.keys(['data', 'links']); | ||
expect(item.relationships.subs[0].data).to.have.all.keys('id', 'type'); | ||
expect(item.relationships.subs).to.have.keys(['data', 'links']); | ||
expect(item.relationships.subs.data[0]).to.have.all.keys('id', 'type'); | ||
} | ||
@@ -57,0 +57,0 @@ }); |
Sorry, the diff of this file is not supported yet
2014
1082229
49