mirror of
https://github.com/typicode/json-server.git
synced 2025-07-30 13:42:11 +08:00
Refactor
This commit is contained in:
@ -32,6 +32,10 @@ var argv = yargs
|
|||||||
routes: {
|
routes: {
|
||||||
alias: 'r',
|
alias: 'r',
|
||||||
description: 'Load routes file'
|
description: 'Load routes file'
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
description: 'Set database id property (e.g. _id)',
|
||||||
|
default: 'id'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.help('help').alias('help', 'h')
|
.help('help').alias('help', 'h')
|
||||||
@ -118,6 +122,10 @@ function start (object, filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.use(router)
|
server.use(router)
|
||||||
|
|
||||||
|
// Custom id
|
||||||
|
router.db._.id = argv.id
|
||||||
|
|
||||||
server.listen(port, argv.host)
|
server.listen(port, argv.host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
"express": "^4.9.5",
|
"express": "^4.9.5",
|
||||||
"got": "^1.2.2",
|
"got": "^1.2.2",
|
||||||
"lodash": "^3.9.2",
|
"lodash": "^3.9.2",
|
||||||
"lowdb": "^0.9.0",
|
"lowdb": "^0.10.0",
|
||||||
"method-override": "^2.1.2",
|
"method-override": "^2.1.2",
|
||||||
"morgan": "^1.3.1",
|
"morgan": "^1.3.1",
|
||||||
"node-uuid": "^1.4.2",
|
"node-uuid": "^1.4.2",
|
||||||
|
77
src/mixins.js
Normal file
77
src/mixins.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
var uuid = require('node-uuid')
|
||||||
|
var pluralize = require('pluralize')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getRemovable: getRemovable,
|
||||||
|
createId: createId,
|
||||||
|
deepQuery: deepQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns document ids that have unsatisfied relations
|
||||||
|
// Example: a comment that references a post that doesn't exist
|
||||||
|
function getRemovable (db) {
|
||||||
|
var _ = this
|
||||||
|
var removable = []
|
||||||
|
_.each(db, function (coll, collName) {
|
||||||
|
_.each(coll, function (doc) {
|
||||||
|
_.each(doc, function (value, key) {
|
||||||
|
if (/Id$/.test(key)) {
|
||||||
|
var refName = pluralize.plural(key.slice(0, -2))
|
||||||
|
// Test if table exists
|
||||||
|
if (db[refName]) {
|
||||||
|
// Test if references is defined in table
|
||||||
|
var ref = _.getById(db[refName], value)
|
||||||
|
if (_.isUndefined(ref)) {
|
||||||
|
removable.push({name: collName, id: doc.id})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return removable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return incremented id or uuid
|
||||||
|
// Used to override underscore-db's createId with utils.createId
|
||||||
|
function createId (coll) {
|
||||||
|
var _ = this
|
||||||
|
var idProperty = _.__id()
|
||||||
|
if (_.isEmpty(coll)) {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
var id = _.max(coll, function (doc) {
|
||||||
|
return doc[idProperty]
|
||||||
|
})[idProperty]
|
||||||
|
|
||||||
|
if (_.isFinite(id)) {
|
||||||
|
// Increment integer id
|
||||||
|
return ++id
|
||||||
|
} else {
|
||||||
|
// Generate string id
|
||||||
|
return uuid()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deepQuery (value, q) {
|
||||||
|
var _ = this
|
||||||
|
if (value && q) {
|
||||||
|
if (_.isArray(value)) {
|
||||||
|
for (var i = 0; i < value.length; i++) {
|
||||||
|
if (deepQuery(value[i], q)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_.isObject(value) && !_.isArray(value)) {
|
||||||
|
for (var k in value) {
|
||||||
|
if (deepQuery(value[k], q)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (value.toString().toLowerCase().indexOf(q) !== -1) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ var _db = require('underscore-db')
|
|||||||
var low = require('lowdb')
|
var low = require('lowdb')
|
||||||
var pluralize = require('pluralize')
|
var pluralize = require('pluralize')
|
||||||
var utils = require('./utils')
|
var utils = require('./utils')
|
||||||
|
var mixins = require('./mixins')
|
||||||
|
|
||||||
module.exports = function (source) {
|
module.exports = function (source) {
|
||||||
// Create router
|
// Create router
|
||||||
@ -26,11 +27,10 @@ module.exports = function (source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add underscore-db methods to db
|
// Add underscore-db methods to db
|
||||||
db.mixin(_db)
|
db._.mixin(_db)
|
||||||
|
|
||||||
// Override underscore-db's createId with utils.createId
|
// Add specific mixins
|
||||||
// utils.createId can generate incremental id or uuid
|
db._.mixin(mixins)
|
||||||
db.mixin({createId: utils.createId})
|
|
||||||
|
|
||||||
// Expose database
|
// Expose database
|
||||||
router.db = db
|
router.db = db
|
||||||
@ -86,7 +86,7 @@ module.exports = function (source) {
|
|||||||
array = db(req.params.resource).filter(function (obj) {
|
array = db(req.params.resource).filter(function (obj) {
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
var value = obj[key]
|
var value = obj[key]
|
||||||
if (utils.deepQuery(value, q)) {
|
if (db._.deepQuery(value, q)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ module.exports = function (source) {
|
|||||||
db(req.params.resource).removeById(utils.toNative(req.params.id))
|
db(req.params.resource).removeById(utils.toNative(req.params.id))
|
||||||
|
|
||||||
// Remove dependents documents
|
// Remove dependents documents
|
||||||
var removable = utils.getRemovable(db.object)
|
var removable = db._.getRemovable(db.object)
|
||||||
|
|
||||||
_.each(removable, function (item) {
|
_.each(removable, function (item) {
|
||||||
db(item.name).removeById(item.id)
|
db(item.name).removeById(item.id)
|
||||||
|
77
src/utils.js
77
src/utils.js
@ -1,6 +1,6 @@
|
|||||||
var _ = require('lodash')
|
module.exports = {
|
||||||
var uuid = require('node-uuid')
|
toNative: toNative
|
||||||
var pluralize = require('pluralize')
|
}
|
||||||
|
|
||||||
// Turns string to native.
|
// Turns string to native.
|
||||||
// Example:
|
// Example:
|
||||||
@ -20,74 +20,3 @@ function toNative (value) {
|
|||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return incremented id or uuid
|
|
||||||
function createId (coll) {
|
|
||||||
if (_.isEmpty(coll)) {
|
|
||||||
return 1
|
|
||||||
} else {
|
|
||||||
var id = _.max(coll, function (doc) {
|
|
||||||
return doc.id
|
|
||||||
}).id
|
|
||||||
|
|
||||||
if (_.isFinite(id)) {
|
|
||||||
// Increment integer id
|
|
||||||
return ++id
|
|
||||||
} else {
|
|
||||||
// Generate string id
|
|
||||||
return uuid()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns document ids that have unsatisfied relations
|
|
||||||
// Example: a comment that references a post that doesn't exist
|
|
||||||
function getRemovable (db) {
|
|
||||||
var removable = []
|
|
||||||
_.each(db, function (coll, collName) {
|
|
||||||
_.each(coll, function (doc) {
|
|
||||||
_.each(doc, function (value, key) {
|
|
||||||
if (/Id$/.test(key)) {
|
|
||||||
var refName = pluralize.plural(key.slice(0, -2))
|
|
||||||
// Test if table exists
|
|
||||||
if (db[refName]) {
|
|
||||||
// Test if references is defined in table
|
|
||||||
var ref = _.findWhere(db[refName], {id: value})
|
|
||||||
if (_.isUndefined(ref)) {
|
|
||||||
removable.push({name: collName, id: doc.id})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return removable
|
|
||||||
}
|
|
||||||
|
|
||||||
function deepQuery (value, q) {
|
|
||||||
if (value && q) {
|
|
||||||
if (_.isArray(value)) {
|
|
||||||
for (var i = 0; i < value.length; i++) {
|
|
||||||
if (deepQuery(value[i], q)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (_.isObject(value) && !_.isArray(value)) {
|
|
||||||
for (var k in value) {
|
|
||||||
if (deepQuery(value[k], q)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (value.toString().toLowerCase().indexOf(q) !== -1) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
toNative: toNative,
|
|
||||||
createId: createId,
|
|
||||||
getRemovable: getRemovable,
|
|
||||||
deepQuery: deepQuery
|
|
||||||
}
|
|
||||||
|
@ -405,4 +405,26 @@ describe('Server', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('router.db._.id', function (done) {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
router.db.object = {
|
||||||
|
posts: [
|
||||||
|
{ _id: 1 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
router.db._.id = '_id'
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should be possible to override id property', function (done) {
|
||||||
|
request(server)
|
||||||
|
.get('/posts/1')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(router.db.object.posts[0])
|
||||||
|
.expect(200, done)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
38
test/mixins.js
Normal file
38
test/mixins.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
var assert = require('assert')
|
||||||
|
var mixins = require('../src/mixins')
|
||||||
|
var _ = require('lodash')
|
||||||
|
var _db = require('underscore-db')
|
||||||
|
|
||||||
|
/* global describe, it */
|
||||||
|
|
||||||
|
describe('mixins', function () {
|
||||||
|
|
||||||
|
describe('getRemovable', function () {
|
||||||
|
|
||||||
|
it('should return removable documents', function () {
|
||||||
|
|
||||||
|
var db = {
|
||||||
|
posts: [
|
||||||
|
{id: 1, comment: 1}
|
||||||
|
],
|
||||||
|
comments: [
|
||||||
|
{id: 1, postId: 1},
|
||||||
|
// Comments below references a post that doesn't exist
|
||||||
|
{id: 2, postId: 2},
|
||||||
|
{id: 3, postId: 2}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
var expected = [
|
||||||
|
{name: 'comments', id: 2},
|
||||||
|
{name: 'comments', id: 3}
|
||||||
|
]
|
||||||
|
|
||||||
|
_.mixin(_db)
|
||||||
|
_.mixin(mixins)
|
||||||
|
|
||||||
|
assert.deepEqual(_.getRemovable(db), expected)
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -5,32 +5,6 @@ var utils = require('../src/utils')
|
|||||||
|
|
||||||
describe('utils', function () {
|
describe('utils', function () {
|
||||||
|
|
||||||
describe('getRemovable', function () {
|
|
||||||
|
|
||||||
it('should return removable documents', function () {
|
|
||||||
|
|
||||||
var db = {
|
|
||||||
posts: [
|
|
||||||
{id: 1, comment: 1}
|
|
||||||
],
|
|
||||||
comments: [
|
|
||||||
{id: 1, postId: 1},
|
|
||||||
// Comments below references a post that doesn't exist
|
|
||||||
{id: 2, postId: 2},
|
|
||||||
{id: 3, postId: 2}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
var expected = [
|
|
||||||
{name: 'comments', id: 2},
|
|
||||||
{name: 'comments', id: 3}
|
|
||||||
]
|
|
||||||
|
|
||||||
assert.deepEqual(utils.getRemovable(db), expected)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('toNative', function () {
|
describe('toNative', function () {
|
||||||
|
|
||||||
it('should convert string to native type', function () {
|
it('should convert string to native type', function () {
|
||||||
|
Reference in New Issue
Block a user