Skip to content

Commit 7281aa9

Browse files
committed
Merge branch 'adamsea-expand-resources'
2 parents 2b99f46 + 6b0d870 commit 7281aa9

File tree

3 files changed

+89
-34
lines changed

3 files changed

+89
-34
lines changed

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Created with <3 for front-end developers who need a quick back-end for prototypi
66

77
* [Egghead.io free video tutorial - Creating demo APIs with json-server](https://egghead.io/lessons/nodejs-creating-demo-apis-with-json-server)
88
* [JSONPlaceholder - Live running version](http://jsonplaceholder.typicode.com)
9-
9+
1010
_See also [hotel](https://github.com/typicode/hotel), a simple process manager for developers._
1111

1212
## Example
@@ -70,6 +70,7 @@ To slice resources, add `_start` and `_end` or `_limit` (an `X-Total-Count` head
7070
```
7171
GET /posts?_start=20&_end=30
7272
GET /posts/1/comments?_start=20&_end=30
73+
GET /posts/1/comments?_start=20&_limit=10
7374
```
7475

7576
To sort resources, add `_sort` and `_order` (ascending order by default).
@@ -85,12 +86,18 @@ To make a full-text search on resources, add `q`.
8586
GET /posts?q=internet
8687
```
8788

88-
To embed other resources, add `_embed`.
89+
To embed resources, add `_embed`.
8990

9091
```
9192
GET /posts/1?_embed=comments
9293
```
9394

95+
To expand inner resources, add `_expand`.
96+
97+
```
98+
GET /comments/1?_expand=post
99+
```
100+
94101
Returns database.
95102

96103
```
@@ -205,7 +212,7 @@ To modify responses, use `router.render()`:
205212
router.render = function (req, res) {
206213
res.jsonp({
207214
body: res.locals.data
208-
})
215+
})
209216
}
210217
```
211218

src/server/router/plural.js

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ module.exports = function (db, name) {
88
// Create router
99
var router = express.Router()
1010

11-
// GET /:resource
12-
// GET /:resource?q=
13-
// GET /:resource?attr=&attr=
14-
// GET /:resource?_end=&*
15-
// GET /:resource?_start=&_end=&*
11+
// GET /name
12+
// GET /name?q=
13+
// GET /name?attr=&attr=
14+
// GET /name?_end=&*
15+
// GET /name?_start=&_end=&*
1616
function list (req, res, next) {
1717

1818
// Filters list
@@ -103,41 +103,59 @@ module.exports = function (db, name) {
103103
next()
104104
}
105105

106-
// GET /:resource/:id
106+
// GET /name/:id
107+
// GET /name/:id?_embed=&_expand
107108
function show (req, res, next) {
108109
var _embed = req.query._embed
110+
var _expand = req.query._expand
109111
var id = utils.toNative(req.params.id)
110-
var resource = db(name)
111-
.getById(id)
112+
var resource = db(name).getById(id)
113+
114+
// Filter empty params
115+
function filter (p) {
116+
return p && p.trim().length > 0
117+
}
112118

113119
if (resource) {
114120
// Clone resource to avoid making changes to the underlying object
115121
resource = _.cloneDeep(resource)
122+
116123
// Always use an array
117-
_embed = _.isArray(_embed) ? _embed : [_embed]
124+
_embed = [].concat(_embed)
125+
_expand = [].concat(_expand)
118126

119127
// Embed other resources based on resource id
120-
_embed.forEach(function (otherResource) {
121-
122-
if (otherResource
123-
&& otherResource.trim().length > 0
124-
&& db.object[otherResource]) {
125-
126-
var query = {}
127-
var prop = pluralize.singular(name) + 'Id'
128-
query[prop] = id
129-
resource[otherResource] = db(otherResource).where(query)
130-
131-
}
132-
})
128+
// /posts/1?_embed=comments
129+
_embed
130+
.filter(filter)
131+
.forEach(function (otherResource) {
132+
if (db.object[otherResource]) {
133+
var query = {}
134+
var singularResource = pluralize.singular(name)
135+
query[singularResource + 'Id'] = id
136+
resource[otherResource] = db(otherResource).where(query)
137+
}
138+
})
139+
140+
// Expand inner resources based on id
141+
// /posts/1?_expand=user
142+
_expand
143+
.filter(filter)
144+
.forEach(function (innerResource) {
145+
var plural = pluralize(innerResource)
146+
if (db.object[plural]) {
147+
var prop = innerResource + 'Id'
148+
resource[innerResource] = db(plural).getById(resource[prop])
149+
}
150+
})
133151

134152
res.locals.data = resource
135153
}
136154

137155
next()
138156
}
139157

140-
// POST /:resource
158+
// POST /name
141159
function create (req, res, next) {
142160
for (var key in req.body) {
143161
req.body[key] = utils.toNative(req.body[key])
@@ -151,8 +169,8 @@ module.exports = function (db, name) {
151169
next()
152170
}
153171

154-
// PUT /:resource/:id
155-
// PATCH /:resource/:id
172+
// PUT /name/:id
173+
// PATCH /name/:id
156174
function update (req, res, next) {
157175
for (var key in req.body) {
158176
req.body[key] = utils.toNative(req.body[key])
@@ -168,7 +186,7 @@ module.exports = function (db, name) {
168186
next()
169187
}
170188

171-
// DELETE /:resource/:id
189+
// DELETE /name/:id
172190
function destroy (req, res, next) {
173191
db(name).removeById(utils.toNative(req.params.id))
174192

test/server/plural.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ describe('Server', function () {
2424
{id: 3, body: 'photo'}
2525
]
2626

27+
db.users = [
28+
{id: 1, username: 'Jim'},
29+
{id: 2, username: 'George'}
30+
]
31+
2732
db.comments = [
28-
{id: 1, body: 'foo', published: true, postId: 1},
29-
{id: 2, body: 'bar', published: false, postId: 1},
30-
{id: 3, body: 'baz', published: false, postId: 2},
31-
{id: 4, body: 'qux', published: true, postId: 2},
32-
{id: 5, body: 'quux', published: false, postId: 2}
33+
{id: 1, body: 'foo', published: true, postId: 1, userId: 1},
34+
{id: 2, body: 'bar', published: false, postId: 1, userId: 2},
35+
{id: 3, body: 'baz', published: false, postId: 2, userId: 1},
36+
{id: 4, body: 'qux', published: true, postId: 2, userId: 2},
37+
{id: 5, body: 'quux', published: false, postId: 2, userId: 1}
3338
]
3439

3540
db.refs = [
@@ -258,6 +263,31 @@ describe('Server', function () {
258263
})
259264
})
260265

266+
describe('GET /:resource/:id?_expand=', function () {
267+
it('should respond with corresponding resource and expanded inner resources', function (done) {
268+
var comments = db.comments[0]
269+
comments.post = db.posts[0]
270+
request(server)
271+
.get('/comments/1?_expand=post')
272+
.expect('Content-Type', /json/)
273+
.expect(comments)
274+
.expect(200, done)
275+
})
276+
})
277+
278+
describe('GET /:resource/:id?_expand=&_expand=', function () {
279+
it('should respond with corresponding resource and expanded inner resources', function (done) {
280+
var comments = db.comments[0]
281+
comments.post = db.posts[0]
282+
comments.user = db.users[0]
283+
request(server)
284+
.get('/comments/1?_expand=post&_expand=user')
285+
.expect('Content-Type', /json/)
286+
.expect(comments)
287+
.expect(200, done)
288+
})
289+
})
290+
261291
describe('POST /:resource', function () {
262292
it('should respond with json, create a resource and increment id',
263293
function (done) {

0 commit comments

Comments
 (0)