From abec9490d99cd6e40964019df38ac1cf6a065dea Mon Sep 17 00:00:00 2001 From: Typicode Date: Tue, 1 Sep 2015 03:08:31 +0200 Subject: [PATCH] Add route GET /resources?_embed&_expand --- src/server/router/plural.js | 72 +++++++++++++++++++++---------------- test/server/plural.js | 62 +++++++++++++++++++++++++++++--- 2 files changed, 100 insertions(+), 34 deletions(-) diff --git a/src/server/router/plural.js b/src/server/router/plural.js index 8d2e054..8f5b59f 100644 --- a/src/server/router/plural.js +++ b/src/server/router/plural.js @@ -8,11 +8,37 @@ module.exports = function (db, name) { // Create router var router = express.Router() + // Embed function used in GET /name and GET /name/id + function embed (resource, e) { + e && [].concat(e) + .forEach(function (externalResource) { + if (db.object[externalResource]) { + var query = {} + var singularResource = pluralize.singular(name) + query[singularResource + 'Id'] = resource.id + resource[externalResource] = db(externalResource).where(query) + } + }) + } + + // Expand function used in GET /name and GET /name/id + function expand (resource, e) { + e && [].concat(e) + .forEach(function (innerResource) { + var plural = pluralize(innerResource) + if (db.object[plural]) { + var prop = innerResource + 'Id' + resource[innerResource] = db(plural).getById(resource[prop]) + } + }) + } + // GET /name // GET /name?q= // GET /name?attr=&attr= - // GET /name?_end=&* - // GET /name?_start=&_end=&* + // GET /name?_end=& + // GET /name?_start=&_end=& + // GET /name?_embed=&_expand= function list (req, res, next) { // Filters list @@ -29,12 +55,16 @@ module.exports = function (db, name) { var _sort = req.query._sort var _order = req.query._order var _limit = req.query._limit + var _embed = req.query._embed + var _expand = req.query._expand delete req.query.q delete req.query._start delete req.query._end delete req.query._sort delete req.query._order delete req.query._limit + delete req.query._embed + delete req.query._expand if (q) { @@ -99,6 +129,14 @@ module.exports = function (db, name) { chain = chain.slice(_start, _start + _limit) } + // embed and expand + chain = chain + .cloneDeep() + .forEach(function (element) { + embed(element, _embed) + expand(element, _expand) + }) + res.locals.data = chain.value() next() } @@ -111,43 +149,17 @@ module.exports = function (db, name) { var id = utils.toNative(req.params.id) var resource = db(name).getById(id) - // Filter empty params - function filter (p) { - return p && p.trim().length > 0 - } - if (resource) { // Clone resource to avoid making changes to the underlying object resource = _.cloneDeep(resource) - // Always use an array - _embed = [].concat(_embed) - _expand = [].concat(_expand) - // Embed other resources based on resource id // /posts/1?_embed=comments - _embed - .filter(filter) - .forEach(function (otherResource) { - if (db.object[otherResource]) { - var query = {} - var singularResource = pluralize.singular(name) - query[singularResource + 'Id'] = id - resource[otherResource] = db(otherResource).where(query) - } - }) + embed(resource, _embed) // Expand inner resources based on id // /posts/1?_expand=user - _expand - .filter(filter) - .forEach(function (innerResource) { - var plural = pluralize(innerResource) - if (db.object[plural]) { - var prop = innerResource + 'Id' - resource[innerResource] = db(plural).getById(resource[prop]) - } - }) + expand(resource, _expand) res.locals.data = resource } diff --git a/test/server/plural.js b/test/server/plural.js index aa2ee12..3820c0a 100644 --- a/test/server/plural.js +++ b/test/server/plural.js @@ -1,5 +1,6 @@ -var request = require('supertest') var assert = require('assert') +var _ = require('lodash') +var request = require('supertest') var jsonServer = require('../../src/server') /* global beforeEach, describe, it */ @@ -38,7 +39,7 @@ describe('Server', function () { ] db.refs = [ - {id: 'abcd-1234', url: 'http://example.com', postId: 1} + {id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1} ] db.deep = [ @@ -238,8 +239,36 @@ describe('Server', function () { }) }) + describe('GET /:resource?_embed=', function () { + it('should respond with corresponding resources and embedded resources', function (done) { + var posts = _.cloneDeep(db.posts) + posts[0].comments = [db.comments[0], db.comments[1]] + posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]] + request(server) + .get('/posts?_embed=comments') + .expect('Content-Type', /json/) + .expect(posts) + .expect(200, done) + }) + }) + + describe('GET /:resource?_embed&_embed=', function () { + it('should respond with corresponding resources and embedded resources', function (done) { + var posts = _.cloneDeep(db.posts) + posts[0].comments = [db.comments[0], db.comments[1]] + posts[0].refs = [db.refs[0]] + posts[1].comments = [db.comments[2], db.comments[3], db.comments[4]] + posts[1].refs = [] + request(server) + .get('/posts?_embed=comments&_embed=refs') + .expect('Content-Type', /json/) + .expect(posts) + .expect(200, done) + }) + }) + describe('GET /:resource/:id?_embed=', function () { - it('should respond with corresponding resource and embedded other resource', function (done) { + it('should respond with corresponding resources and embedded resources', function (done) { var posts = db.posts[0] posts.comments = [db.comments[0], db.comments[1]] request(server) @@ -251,7 +280,7 @@ describe('Server', function () { }) describe('GET /:resource/:id?_embed=&_embed=', function () { - it('should respond with corresponding resource and embedded other resources', function (done) { + it('should respond with corresponding resource and embedded resources', function (done) { var posts = db.posts[0] posts.comments = [db.comments[0], db.comments[1]] posts.refs = [db.refs[0]] @@ -263,6 +292,18 @@ describe('Server', function () { }) }) + describe('GET /:resource?_expand=', function () { + it('should respond with corresponding resource and expanded inner resources', function (done) { + var refs = _.cloneDeep(db.refs) + refs[0].post = db.posts[0] + request(server) + .get('/refs?_expand=post') + .expect('Content-Type', /json/) + .expect(refs) + .expect(200, done) + }) + }) + describe('GET /:resource/:id?_expand=', function () { it('should respond with corresponding resource and expanded inner resources', function (done) { var comments = db.comments[0] @@ -275,6 +316,19 @@ describe('Server', function () { }) }) + describe('GET /:resource?_expand=&_expand', function () { + it('should respond with corresponding resource and expanded inner resources', function (done) { + var refs = _.cloneDeep(db.refs) + refs[0].post = db.posts[0] + refs[0].user = db.users[0] + request(server) + .get('/refs?_expand=post&_expand=user') + .expect('Content-Type', /json/) + .expect(refs) + .expect(200, done) + }) + }) + describe('GET /:resource/:id?_expand=&_expand=', function () { it('should respond with corresponding resource and expanded inner resources', function (done) { var comments = db.comments[0]