Skip to content

Commit 95f334f

Browse files
committed
Add singular resources
1 parent f277035 commit 95f334f

File tree

6 files changed

+222
-77
lines changed

6 files changed

+222
-77
lines changed

src/server/router/index.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
var express = require('express')
2+
var methodOverride = require('method-override')
3+
var bodyParser = require('body-parser')
4+
var _ = require('lodash')
5+
var _db = require('underscore-db')
6+
var low = require('lowdb')
7+
var plural = require('./plural')
8+
var nested = require('./nested')
9+
var singular = require('./singular')
10+
var mixins = require('../mixins')
11+
12+
module.exports = function (source) {
13+
14+
// Create router
15+
var router = express.Router()
16+
17+
// Add middlewares
18+
router.use(bodyParser.json({limit: '10mb'}))
19+
router.use(bodyParser.urlencoded({extended: false}))
20+
router.use(methodOverride())
21+
22+
// Create database
23+
var db
24+
if (_.isObject(source)) {
25+
db = low()
26+
db.object = source
27+
} else {
28+
db = low(source)
29+
}
30+
31+
// Add underscore-db methods to db
32+
db._.mixin(_db)
33+
34+
// Add specific mixins
35+
db._.mixin(mixins)
36+
37+
// Expose database
38+
router.db = db
39+
40+
// Expose database
41+
router.db = db
42+
43+
// Expose render
44+
router.render = function (req, res) {
45+
res.jsonp(res.locals.data)
46+
}
47+
48+
// GET /db
49+
function showDatabase (req, res, next) {
50+
res.locals.data = db.object
51+
next()
52+
}
53+
54+
router.get('/db', showDatabase)
55+
56+
router.use(nested())
57+
58+
// Create routes
59+
for (var prop in db.object) {
60+
if (_.isPlainObject(db.object[prop])) {
61+
router.use('/' + prop, singular(db, prop))
62+
continue
63+
}
64+
65+
if (_.isArray(db.object[prop])) {
66+
router.use('/' + prop, plural(db, prop))
67+
continue
68+
}
69+
70+
throw new Error('Unsupported type')
71+
72+
}
73+
74+
router.use(function (req, res) {
75+
if (!res.locals.data) {
76+
res.status(404)
77+
res.locals.data = {}
78+
}
79+
80+
router.render(req, res)
81+
})
82+
83+
return router
84+
}

src/server/router/nested.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
var express = require('express')
2+
var pluralize = require('pluralize')
3+
var utils = require('../utils')
4+
5+
module.exports = function () {
6+
7+
var router = express.Router()
8+
9+
// Rewrite url to /:nested?:resourceId=:id
10+
router.get('/:resource/:id/:nested', function (req, res, next) {
11+
var prop = pluralize.singular(req.params.resource)
12+
req.query[prop + 'Id'] = utils.toNative(req.params.id)
13+
req.url = '/' + req.params.nested
14+
next()
15+
})
16+
17+
return router
18+
}

src/server/router.js renamed to src/server/router/plural.js

Lines changed: 13 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,25 @@
11
var express = require('express')
2-
var methodOverride = require('method-override')
3-
var bodyParser = require('body-parser')
42
var _ = require('lodash')
5-
var _db = require('underscore-db')
6-
var low = require('lowdb')
73
var pluralize = require('pluralize')
8-
var utils = require('./utils')
9-
var mixins = require('./mixins')
4+
var utils = require('../utils')
5+
6+
module.exports = function (db, name) {
107

11-
module.exports = function (source) {
128
// Create router
139
var router = express.Router()
1410

15-
// Add middlewares
16-
router.use(bodyParser.json({limit: '10mb'}))
17-
router.use(bodyParser.urlencoded({extended: false}))
18-
router.use(methodOverride())
19-
20-
// Create database
21-
var db
22-
if (_.isObject(source)) {
23-
db = low()
24-
db.object = source
25-
} else {
26-
db = low(source)
27-
}
28-
29-
// Add underscore-db methods to db
30-
db._.mixin(_db)
31-
32-
// Add specific mixins
33-
db._.mixin(mixins)
34-
35-
// Expose database
36-
router.db = db
37-
38-
// Expose render
39-
router.render = function (req, res) {
40-
res.jsonp(res.locals.data)
41-
}
42-
43-
// GET /db
44-
function showDatabase (req, res, next) {
45-
res.locals.data = db.object
46-
next()
47-
}
48-
4911
// GET /:resource
5012
// GET /:resource?q=
5113
// GET /:resource?attr=&attr=
52-
// GET /:parent/:parentId/:resource?attr=&attr=
53-
// GET /*?*&_end=
54-
// GET /*?*&_start=&_end=
14+
// GET /:resource?_end=&*
15+
// GET /:resource?_start=&_end=&*
5516
function list (req, res, next) {
56-
// Test if resource exists
57-
if (!db.object.hasOwnProperty(req.params.resource)) {
58-
res.status(404)
59-
return next()
60-
}
6117

6218
// Filters list
6319
var filters = {}
6420

6521
// Resource chain
66-
var chain = db(req.params.resource).chain()
22+
var chain = db(name).chain()
6723

6824
// Remove q, _start, _end, ... from req.query to avoid filtering using those
6925
// parameters
@@ -96,12 +52,6 @@ module.exports = function (source) {
9652

9753
}
9854

99-
// Add :parentId filter in case URL is like /:parent/:parentId/:resource
100-
if (req.params.parent) {
101-
var parent = pluralize.singular(req.params.parent)
102-
filters[parent + 'Id'] = +req.params.parentId
103-
}
104-
10555
// Add query parameters filters
10656
// Convert query parameters to their native counterparts
10757
for (var key in req.query) {
@@ -157,7 +107,7 @@ module.exports = function (source) {
157107
function show (req, res, next) {
158108
var _embed = req.query._embed
159109
var id = utils.toNative(req.params.id)
160-
var resource = db(req.params.resource)
110+
var resource = db(name)
161111
.getById(id)
162112

163113
if (resource) {
@@ -173,17 +123,14 @@ module.exports = function (source) {
173123
&& otherResource.trim().length > 0
174124
&& db.object[otherResource]) {
175125
var query = {}
176-
var prop = pluralize.singular(req.params.resource) + 'Id'
126+
var prop = pluralize.singular(name) + 'Id'
177127
query[prop] = id
178128
resource[otherResource] = db(otherResource).where(query)
179129

180130
}
181131
})
182132

183133
res.locals.data = resource
184-
} else {
185-
res.status(404)
186-
res.locals.data = {}
187134
}
188135

189136
next()
@@ -195,7 +142,7 @@ module.exports = function (source) {
195142
req.body[key] = utils.toNative(req.body[key])
196143
}
197144

198-
var resource = db(req.params.resource)
145+
var resource = db(name)
199146
.insert(req.body)
200147

201148
res.status(201)
@@ -210,22 +157,19 @@ module.exports = function (source) {
210157
req.body[key] = utils.toNative(req.body[key])
211158
}
212159

213-
var resource = db(req.params.resource)
160+
var resource = db(name)
214161
.updateById(utils.toNative(req.params.id), req.body)
215162

216163
if (resource) {
217164
res.locals.data = resource
218-
} else {
219-
res.status(404)
220-
res.locals.data = {}
221165
}
222166

223167
next()
224168
}
225169

226170
// DELETE /:resource/:id
227171
function destroy (req, res, next) {
228-
db(req.params.resource).removeById(utils.toNative(req.params.id))
172+
db(name).removeById(utils.toNative(req.params.id))
229173

230174
// Remove dependents documents
231175
var removable = db._.getRemovable(db.object)
@@ -238,23 +182,15 @@ module.exports = function (source) {
238182
next()
239183
}
240184

241-
router.get('/db', showDatabase, router.render)
242-
243-
router.route('/:resource')
185+
router.route('/')
244186
.get(list)
245187
.post(create)
246188

247-
router.route('/:resource/:id')
189+
router.route('/:id')
248190
.get(show)
249191
.put(update)
250192
.patch(update)
251193
.delete(destroy)
252194

253-
router.get('/:parent/:parentId/:resource', list)
254-
255-
router.all('*', function (req, res) {
256-
router.render(req, res)
257-
})
258-
259195
return router
260196
}

src/server/router/singular.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
var express = require('express')
2+
var utils = require('../utils')
3+
4+
module.exports = function (db, name) {
5+
6+
var router = express.Router()
7+
8+
function show (req, res, next) {
9+
res.locals.data = db.object[name]
10+
next()
11+
}
12+
13+
function create (req, res, next) {
14+
for (var prop in req.body) {
15+
req.body[prop] = utils.toNative(req.body[prop])
16+
}
17+
18+
res.locals.data = db.object[name] = req.body
19+
res.status(201)
20+
next()
21+
}
22+
23+
function update (req, res, next) {
24+
for (var prop in req.body) {
25+
db.object[name][prop] = utils.toNative(req.body[prop])
26+
}
27+
28+
res.locals.data = db.object[name]
29+
next()
30+
}
31+
32+
router.route('/')
33+
.get(show)
34+
.post(create)
35+
.put(update)
36+
.patch(update)
37+
38+
return router
39+
40+
}
File renamed without changes.

test/server/singular.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
var request = require('supertest')
2+
var assert = require('assert')
3+
var jsonServer = require('../../src/server')
4+
5+
/* global beforeEach, describe, it */
6+
7+
describe('Server', function () {
8+
9+
var server
10+
var router
11+
var db
12+
13+
beforeEach(function () {
14+
db = {}
15+
16+
db.user = {
17+
name: 'foo',
18+
19+
}
20+
21+
server = jsonServer.create()
22+
router = jsonServer.router(db)
23+
server.use(router)
24+
})
25+
26+
describe('GET /:resource', function () {
27+
it('should respond with corresponding resource', function (done) {
28+
request(server)
29+
.get('/user')
30+
.expect(db.user)
31+
.expect(200, done)
32+
})
33+
})
34+
35+
describe('POST /:resource', function () {
36+
it('should create resource', function (done) {
37+
var user = { name: 'bar' }
38+
request(server)
39+
.post('/user')
40+
.send(user)
41+
.expect(user)
42+
.expect(201, done)
43+
})
44+
})
45+
46+
describe('PUT /:resource', function () {
47+
it('should uptade resource', function (done) {
48+
var user = { name: 'bar' }
49+
request(server)
50+
.put('/user')
51+
.send(user)
52+
.expect(db.user)
53+
.expect(200, done)
54+
})
55+
})
56+
57+
describe('PATCH /:resource', function () {
58+
it('should uptade resource', function (done) {
59+
request(server)
60+
.patch('/user')
61+
.send({ name: 'bar' })
62+
.expect({ name: 'bar', email: '[email protected]' })
63+
.expect(200, done)
64+
})
65+
})
66+
67+
})

0 commit comments

Comments
 (0)