This commit is contained in:
Typicode
2015-06-16 01:45:25 +02:00
parent c3e092ca96
commit cd710213e0
8 changed files with 155 additions and 107 deletions

View File

@ -32,6 +32,10 @@ var argv = yargs
routes: {
alias: 'r',
description: 'Load routes file'
},
id: {
description: 'Set database id property (e.g. _id)',
default: 'id'
}
})
.help('help').alias('help', 'h')
@ -118,6 +122,10 @@ function start (object, filename) {
}
server.use(router)
// Custom id
router.db._.id = argv.id
server.listen(port, argv.host)
}

View File

@ -15,7 +15,7 @@
"express": "^4.9.5",
"got": "^1.2.2",
"lodash": "^3.9.2",
"lowdb": "^0.9.0",
"lowdb": "^0.10.0",
"method-override": "^2.1.2",
"morgan": "^1.3.1",
"node-uuid": "^1.4.2",

77
src/mixins.js Normal file
View 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
}
}
}

View File

@ -6,6 +6,7 @@ var _db = require('underscore-db')
var low = require('lowdb')
var pluralize = require('pluralize')
var utils = require('./utils')
var mixins = require('./mixins')
module.exports = function (source) {
// Create router
@ -26,11 +27,10 @@ module.exports = function (source) {
}
// Add underscore-db methods to db
db.mixin(_db)
db._.mixin(_db)
// Override underscore-db's createId with utils.createId
// utils.createId can generate incremental id or uuid
db.mixin({createId: utils.createId})
// Add specific mixins
db._.mixin(mixins)
// Expose database
router.db = db
@ -86,7 +86,7 @@ module.exports = function (source) {
array = db(req.params.resource).filter(function (obj) {
for (var key in obj) {
var value = obj[key]
if (utils.deepQuery(value, q)) {
if (db._.deepQuery(value, q)) {
return true
}
}
@ -226,7 +226,7 @@ module.exports = function (source) {
db(req.params.resource).removeById(utils.toNative(req.params.id))
// Remove dependents documents
var removable = utils.getRemovable(db.object)
var removable = db._.getRemovable(db.object)
_.each(removable, function (item) {
db(item.name).removeById(item.id)

View File

@ -1,6 +1,6 @@
var _ = require('lodash')
var uuid = require('node-uuid')
var pluralize = require('pluralize')
module.exports = {
toNative: toNative
}
// Turns string to native.
// Example:
@ -20,74 +20,3 @@ function toNative (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
}

View File

@ -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
View 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)
})
})
})

View File

@ -5,32 +5,6 @@ var utils = require('../src/utils')
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 () {
it('should convert string to native type', function () {