Remove automatic type conversion

This commit is contained in:
typicode
2016-10-01 17:30:16 +02:00
parent e5473811b1
commit dbf9ed9a5c
6 changed files with 55 additions and 79 deletions

View File

@ -25,7 +25,7 @@
"pluralize": "^3.0.0",
"request": "^2.72.0",
"server-destroy": "^1.0.1",
"underscore-db": "^0.10.0",
"underscore-db": "^0.12.0",
"update-notifier": "^1.0.2",
"yargs": "^4.2.0"
},

View File

@ -1,6 +1,5 @@
var express = require('express')
var pluralize = require('pluralize')
var utils = require('../utils')
module.exports = function () {
var router = express.Router()
@ -8,7 +7,7 @@ module.exports = function () {
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request query
function get (req, res, next) {
var prop = pluralize.singular(req.params.resource)
req.query[prop + 'Id'] = utils.toNative(req.params.id)
req.query[prop + 'Id'] = req.params.id
req.url = '/' + req.params.nested
next()
}
@ -16,7 +15,7 @@ module.exports = function () {
// Rewrite URL (/:resource/:id/:nested -> /:nested) and request body
function post (req, res, next) {
var prop = pluralize.singular(req.params.resource)
req.body[prop + 'Id'] = utils.toNative(req.params.id)
req.body[prop + 'Id'] = req.params.id
req.url = '/' + req.params.nested
next()
}

View File

@ -107,7 +107,6 @@ module.exports = function (db, name) {
chain = chain.filter(function (element) {
return arr
.map(utils.toNative)
.map(function (value) {
var isDifferent = key.indexOf('_ne') !== -1
var isRange = key.indexOf('_lte') !== -1 || key.indexOf('_gte') !== -1
@ -115,6 +114,10 @@ module.exports = function (db, name) {
var path = key.replace(/(_lte|_gte|_ne|_like)$/, '')
var elementValue = _.get(element, path)
if (!elementValue) {
return false
}
if (isRange) {
var isLowerThan = key.indexOf('_gte') !== -1
@ -124,11 +127,11 @@ module.exports = function (db, name) {
return value >= elementValue
}
} else if (isDifferent) {
return value !== elementValue
return value !== elementValue.toString()
} else if (isLike) {
return new RegExp(value, 'i').test(elementValue)
return new RegExp(value, 'i').test(elementValue.toString())
} else {
return _.matchesProperty(key, value)(element)
return value === elementValue.toString()
}
}).reduce(function (a, b) {
return a || b
@ -209,8 +212,7 @@ module.exports = function (db, name) {
function show (req, res, next) {
var _embed = req.query._embed
var _expand = req.query._expand
var id = utils.toNative(req.params.id)
var resource = db.get(name).getById(id).value()
var resource = db.get(name).getById(req.params.id).value()
if (resource) {
// Clone resource to avoid making changes to the underlying object
@ -232,10 +234,6 @@ module.exports = function (db, name) {
// POST /name
function create (req, res, next) {
for (var key in req.body) {
req.body[key] = utils.toNative(req.body[key])
}
var resource = db.get(name)
.insert(req.body)
.value()
@ -248,11 +246,7 @@ module.exports = function (db, name) {
// PUT /name/:id
// PATCH /name/:id
function update (req, res, next) {
for (var key in req.body) {
req.body[key] = utils.toNative(req.body[key])
}
var id = utils.toNative(req.params.id)
var id = req.params.id
var chain = db.get(name)
chain = req.method === 'PATCH'
@ -270,7 +264,7 @@ module.exports = function (db, name) {
// DELETE /name/:id
function destroy (req, res, next) {
var resource = db.get(name).removeById(utils.toNative(req.params.id)).value()
var resource = db.get(name).removeById(req.params.id).value()
// Remove dependents documents
var removable = db._.getRemovable(db.getState())

View File

@ -1,29 +1,7 @@
module.exports = {
toNative: toNative,
getPage: getPage
}
// Turns string to native.
// Example:
// 'true' -> true
// '1' -> 1
function toNative (value) {
if (typeof value === 'string') {
if (
value === '' ||
value.trim() !== value ||
(value.length > 1 && value[0] === '0')
) {
return value
} else if (value === 'true' || value === 'false') {
return value === 'true'
} else if (!isNaN(+value)) {
return +value
}
}
return value
}
function getPage (array, page, perPage) {
var obj = {}
var start = (page - 1) * perPage

View File

@ -24,8 +24,8 @@ describe('Server', function () {
]
db.users = [
{id: 1, username: 'Jim'},
{id: 2, username: 'George'}
{id: 1, username: 'Jim', tel: '0123'},
{id: 2, username: 'George', tel: '123'}
]
db.comments = [
@ -40,6 +40,10 @@ describe('Server', function () {
{id: 'abcd-1234', url: 'http://example.com', postId: 1, userId: 1}
]
db.stringIds = [
{id: '1234'}
]
db.deep = [
{ a: { b: 1 } },
{ a: 1 }
@ -117,6 +121,14 @@ describe('Server', function () {
.expect(200, done)
})
it('should be strict', function (done) {
request(server)
.get('/users?tel=123')
.expect('Content-Type', /json/)
.expect([db.users[1]])
.expect(200, done)
})
it('should support multiple filters', function (done) {
request(server)
.get('/comments?id=1&id=2')
@ -349,6 +361,14 @@ describe('Server', function () {
.expect(200, done)
})
it('should support integer id as string', function (done) {
request(server)
.get('/stringIds/1234')
.expect('Content-Type', /json/)
.expect(db.stringIds[0])
.expect(200, done)
})
it('should respond with 404 if resource is not found', function (done) {
request(server)
.get('/posts/9001')
@ -388,25 +408,25 @@ describe('Server', function () {
describe('GET /:resource/:id?_embed=', function () {
it('should respond with corresponding resources and embedded resources', function (done) {
var posts = db.posts[0]
posts.comments = [db.comments[0], db.comments[1]]
var post = _.cloneDeep(db.posts[0])
post.comments = [db.comments[0], db.comments[1]]
request(server)
.get('/posts/1?_embed=comments')
.expect('Content-Type', /json/)
.expect(posts)
.expect(post)
.expect(200, done)
})
})
describe('GET /:resource/:id?_embed=&_embed=', function () {
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]]
var post = _.cloneDeep(db.posts[0])
post.comments = [db.comments[0], db.comments[1]]
post.refs = [db.refs[0]]
request(server)
.get('/posts/1?_embed=comments&_embed=refs')
.expect('Content-Type', /json/)
.expect(posts)
.expect(post)
.expect(200, done)
})
})
@ -425,12 +445,12 @@ describe('Server', function () {
describe('GET /:resource/:id?_expand=', function () {
it('should respond with corresponding resource and expanded inner resources', function (done) {
var comments = db.comments[0]
comments.post = db.posts[0]
var comment = _.cloneDeep(db.comments[0])
comment.post = db.posts[0]
request(server)
.get('/comments/1?_expand=post')
.expect('Content-Type', /json/)
.expect(comments)
.expect(comment)
.expect(200, done)
})
})
@ -466,7 +486,7 @@ describe('Server', function () {
function (done) {
request(server)
.post('/posts')
.send({body: 'foo', booleanValue: 'true', integerValue: '1'})
.send({body: 'foo', booleanValue: true, integerValue: 1})
.expect('Content-Type', /json/)
.expect({id: 3, body: 'foo', booleanValue: true, integerValue: 1})
.expect(201)
@ -475,23 +495,26 @@ describe('Server', function () {
assert.equal(db.posts.length, 3)
done()
})
})
}
)
it('should support x-www-form-urlencoded',
function (done) {
request(server)
.post('/posts')
.type('form')
.send({body: 'foo'})
.send({body: 'foo', booleanValue: true, integerValue: 1})
.expect('Content-Type', /json/)
.expect({id: 3, body: 'foo'})
// x-www-form-urlencoded will convert to string
.expect({id: 3, body: 'foo', booleanValue: 'true', integerValue: '1'})
.expect(201)
.end(function (err, res) {
if (err) return done(err)
assert.equal(db.posts.length, 3)
done()
})
})
}
)
it('should respond with json, create a resource and generate string id',
function (done) {
@ -525,7 +548,7 @@ describe('Server', function () {
request(server)
.put('/posts/1')
// body property omitted to test that the resource is replaced
.send({id: 1, booleanValue: 'true', integerValue: '1'})
.send(post)
.expect('Content-Type', /json/)
.expect(post)
.expect(200)
@ -540,7 +563,7 @@ describe('Server', function () {
it('should respond with 404 if resource is not found', function (done) {
request(server)
.put('/posts/9001')
.send({id: 1, body: 'bar', booleanValue: 'true', integerValue: '1'})
.send({id: 1, body: 'bar'})
.expect('Content-Type', /json/)
.expect({})
.expect(404, done)

View File

@ -4,24 +4,6 @@ var utils = require('../../src/server/utils')
/* global describe, it */
describe('utils', function () {
describe('toNative', function () {
it('should convert string to native type', function () {
// should convert
assert.strictEqual(utils.toNative('1'), 1)
assert.strictEqual(utils.toNative('0'), 0)
assert.strictEqual(utils.toNative('true'), true)
// should not convert
assert.strictEqual(utils.toNative(''), '')
assert.strictEqual(utils.toNative('\t\n'), '\t\n')
assert.strictEqual(utils.toNative('1 '), '1 ')
assert.strictEqual(utils.toNative('01'), '01')
assert.strictEqual(utils.toNative(' 1'), ' 1')
assert.strictEqual(utils.toNative('string'), 'string')
assert.strictEqual(utils.toNative(1), 1)
assert.strictEqual(utils.toNative(true), true)
})
})
describe('getPage', function () {
var array = [1, 2, 3, 4, 5]
var perPage = 2