mirror of
https://github.com/zhigang1992/deployd.git
synced 2026-04-28 17:35:50 +08:00
mdoq refactor, resources, routes
This commit is contained in:
30
README.md
30
README.md
@@ -14,8 +14,8 @@ Extensible, distributed resource server.
|
||||
## Hello World
|
||||
|
||||
var dpd = require('deployd')
|
||||
, server = dpd()
|
||||
, client = require('mdoq').require('mdoq-http').use('http://localhost:3000')
|
||||
, server = dpd('My Todo App')
|
||||
, client = require('mdoq').require('mdoq-http').use('http://user:pass@localhost:3000')
|
||||
, resources = client.use('/resources')
|
||||
, todos = client.use('/todos')
|
||||
;
|
||||
@@ -36,25 +36,21 @@ Extensible, distributed resource server.
|
||||
}
|
||||
};
|
||||
|
||||
resources.use('/todos').post(description, function(err, description) {
|
||||
console.info('added todo description to resource graph');
|
||||
});
|
||||
|
||||
server.listen('localhost', 3000);
|
||||
|
||||
Once the server is listening, we can interact with resources over http:
|
||||
|
||||
server.on('listening', function () {
|
||||
todos.post({title: 'feed the dog'}, function(err, todo) {
|
||||
console.log(todo._id); // the todos unique identifier
|
||||
todos
|
||||
.use('/' + todo._id)
|
||||
.put({completed: true}, function (err, todo) {
|
||||
console.log(todo); // {title: 'feed the dog', completed: true}
|
||||
})
|
||||
;
|
||||
})
|
||||
})
|
||||
server.on('listening', function() {
|
||||
// describe a new type of resource
|
||||
resources.use('/todos').post(description, function(err, description) {
|
||||
console.info('added todo description to resource graph');
|
||||
|
||||
// todos are now available
|
||||
todos.post({title: 'feed the dog'}, function(err, todo) {
|
||||
console.log(todo._id); // the todos unique identifier
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
## Resource Graph
|
||||
|
||||
|
||||
37
examples/todo.server.js
Normal file
37
examples/todo.server.js
Normal file
@@ -0,0 +1,37 @@
|
||||
var dpd = require('deployd')
|
||||
, server = dpd('My Todo App')
|
||||
, client = require('mdoq').require('mdoq-http').use('http://user:pass@localhost:3000')
|
||||
, resources = client.use('/resources')
|
||||
, todos = client.use('/todos')
|
||||
;
|
||||
|
||||
var description = {
|
||||
type: 'data',
|
||||
name: 'todo',
|
||||
properties: {
|
||||
title: {
|
||||
description: 'the title of the todo',
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
completed: {
|
||||
description: 'the state of the todo',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
server.on('listening', function() {
|
||||
// describe a new type of resource
|
||||
resources.use('/todos').post(description, function(err, description) {
|
||||
console.info('added todo description to resource graph');
|
||||
|
||||
// todos are now available
|
||||
todos.post({title: 'feed the dog'}, function(err, todo) {
|
||||
console.log('err', err, 'todo', todo);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(3000);
|
||||
1
lib/client.js
Normal file
1
lib/client.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('mdoq').require('mdoq-http');
|
||||
@@ -10,6 +10,6 @@ var express = require('express')
|
||||
* Export the deployd constructor.
|
||||
*/
|
||||
|
||||
module.exports = function () {
|
||||
return require('./server');
|
||||
module.exports = function (name) {
|
||||
return require('./server')(name);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
var resources = require('./storage').use('/resources');
|
||||
|
||||
var debug = require('mdoq').util.debug;
|
||||
|
||||
module.exports = require('./storage')
|
||||
.use('/resources')
|
||||
;
|
||||
|
||||
44
lib/router.js
Normal file
44
lib/router.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var storage = require('./storage')
|
||||
, resources = require('./resources')
|
||||
, revalidator = require('revalidator')
|
||||
;
|
||||
|
||||
module.exports = function (req, res, next) {
|
||||
var path = req.url.split('?')[0];
|
||||
|
||||
resources.get({path: path}, function (err, resource) {
|
||||
|
||||
// HACK - REMOVE ONCE `first()` LANDS IN MDOQ-MONGODB
|
||||
|
||||
resource = resource && resource[0] || resource;
|
||||
|
||||
if(resource && tryingToModify(req)) {
|
||||
if(resource.settings) {
|
||||
var result = revalidator.validate(req.body, {properties: resource.settings});
|
||||
|
||||
if(result.valid) {
|
||||
storage.proxy().call(this, req, res, next);
|
||||
} else {
|
||||
res.send(result);
|
||||
}
|
||||
} else {
|
||||
storage.proxy().call(this, req, res, next);
|
||||
}
|
||||
} else if(resource) {
|
||||
storage.exec(req, function (err, r) {
|
||||
res.send(err || r);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function tryingToModify(req) {
|
||||
var method = req.method;
|
||||
return method === 'POST' || method === 'PUT';
|
||||
}
|
||||
@@ -1,8 +1,37 @@
|
||||
var express = require('express')
|
||||
, server = module.exports = express.createServer()
|
||||
var dpd = require('./deployd')
|
||||
, name = dpd.name
|
||||
, express = require('express')
|
||||
, server = express.createServer(express.bodyParser())
|
||||
, resources = require('./resources')
|
||||
, router = require('./router')
|
||||
, types = require('./types')
|
||||
;
|
||||
|
||||
server.get('/resources', function () {
|
||||
|
||||
})
|
||||
/**
|
||||
* Serve storage at each resource route.
|
||||
*/
|
||||
|
||||
server.use(router);
|
||||
|
||||
/**
|
||||
* Serve resources over http.
|
||||
*/
|
||||
|
||||
server.use('/resources', resources.proxy());
|
||||
|
||||
/**
|
||||
* Serve resource types over http.
|
||||
*/
|
||||
|
||||
server.get('/types', function (req, res) {
|
||||
res.send(types);
|
||||
});
|
||||
|
||||
/**
|
||||
* Export a function to mount the new server to a name.
|
||||
*/
|
||||
|
||||
module.exports = function (name) {
|
||||
server.name = name || 'deployd';
|
||||
return server;
|
||||
};
|
||||
@@ -1 +1,4 @@
|
||||
module.exports = require('mdoq').require('mdoq-mongodb');
|
||||
module.exports = require('mdoq')
|
||||
.require('mdoq-mongodb')
|
||||
.use('mongodb://localhost/dpd-testing')
|
||||
;
|
||||
12
lib/types.js
Normal file
12
lib/types.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
|
||||
Collection: {
|
||||
defaultPath: '/my-objects'
|
||||
},
|
||||
|
||||
UserCollection: {
|
||||
label: 'Users Collection',
|
||||
defaultPath: '/users'
|
||||
}
|
||||
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"author": "Ritchie Martori",
|
||||
"name": "deployd",
|
||||
"version": "0.0.0",
|
||||
"version": "0.3.0",
|
||||
"repository": {
|
||||
"url": "git://github.com/deployd/deployd.git"
|
||||
},
|
||||
@@ -9,6 +9,11 @@
|
||||
"node": ">= 0.6.x"
|
||||
},
|
||||
"main":"index",
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"mdoq-http": "0.2.2",
|
||||
"mdoq-mongodb": "0.2.2",
|
||||
"revalidator": "0.1.0",
|
||||
"express": "2.5.8"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
||||
|
||||
91
test/deployd.test.js
Normal file
91
test/deployd.test.js
Normal file
@@ -0,0 +1,91 @@
|
||||
var expect = require('chai').expect
|
||||
, mdoq = require('mdoq')
|
||||
, client = require('../lib/client').use(mdoq.util.debug)
|
||||
, dpd = require('../')
|
||||
, server = dpd('My Todo App')
|
||||
, tclient = client.use('http://localhost:3003')
|
||||
, resources = tclient.use('/resources')
|
||||
, todos = tclient.use('/todos')
|
||||
, routes = tclient.use('/routes')
|
||||
;
|
||||
|
||||
describe('Booting a server', function(){
|
||||
it('should have the given name', function() {
|
||||
var name = 'my simple server'
|
||||
, server = dpd(name);
|
||||
|
||||
expect(server.name).to.equal(name);
|
||||
})
|
||||
|
||||
it('should have a default name of deployd', function() {
|
||||
var server = dpd();
|
||||
expect(server.name).to.equal('deployd');
|
||||
})
|
||||
|
||||
it('should start listening on the given port', function(done) {
|
||||
var server = dpd('test server')
|
||||
, port = 2304;
|
||||
|
||||
server.on('listening', function () {
|
||||
// server emits listening more than once!
|
||||
if(!server.closing) server.close();
|
||||
});
|
||||
|
||||
server.on('close', function () {
|
||||
server.closing = true;
|
||||
done();
|
||||
});
|
||||
|
||||
server.listen(port);
|
||||
})
|
||||
})
|
||||
|
||||
describe('Resource Types', function(){
|
||||
it('should be able to be described from a client', function(done) {
|
||||
var resource = {
|
||||
type: 'Collection',
|
||||
path: '/todos',
|
||||
settings: {
|
||||
title: {
|
||||
description: 'the title of the todo',
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
completed: {
|
||||
description: 'the state of the todo',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
server.on('listening', function() {
|
||||
// describe a new type of resource
|
||||
resources.post(resource, done);
|
||||
});
|
||||
|
||||
server.listen(3003);
|
||||
})
|
||||
|
||||
it('should now have a resource type', function(done) {
|
||||
resources.get(function (err, todos) {
|
||||
expect(todos).to.exist;
|
||||
expect(todos).to.have.length(1);
|
||||
expect(todos[0].path).to.equal('/todos');
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
|
||||
it('should save a new todo', function(done) {
|
||||
var eg = {title: 'feed the dog'};
|
||||
|
||||
todos.post(eg, function (err) {
|
||||
todos.get(eg, function (err, todo) {
|
||||
// HACK - need first()
|
||||
if(todo.length) todo = todo[0];
|
||||
expect(todo.title).to.equal(eg.title);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
89
test/resources.test.js
Normal file
89
test/resources.test.js
Normal file
@@ -0,0 +1,89 @@
|
||||
var resources = require('../')
|
||||
, expect = require('chai').expect
|
||||
, resources = require('../lib/resources')
|
||||
;
|
||||
|
||||
var description = {
|
||||
type: 'Data',
|
||||
properties: {
|
||||
title: {
|
||||
description: 'the title of the todo',
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
completed: {
|
||||
description: 'the state of the todo',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function clean() {
|
||||
describe('resources clean', function(){
|
||||
it('should remove all resources', function(done) {
|
||||
resources.del(function (err, res) {
|
||||
resources.get(function (err, res) {
|
||||
expect(res).to.not.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('Resource Actions', function(){
|
||||
|
||||
clean();
|
||||
|
||||
describe('Adding', function(){
|
||||
it('should add a new resource', function(done) {
|
||||
resources.post(description, function (err, r) {
|
||||
description._id = r._id;
|
||||
expect(r._id).to.exist;
|
||||
resources.get({_id: r._id}, function (err, r) {
|
||||
expect(r).to.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('resources.put()', function(){
|
||||
it('should update the resource', function(done) {
|
||||
resources
|
||||
.get({_id: description._id})
|
||||
// change title to task
|
||||
.put({$set: {'properties.title': null, 'properties.task': description.properties.title}}, function (err, r) {
|
||||
resources.get({_id: description._id}, function (err, r) {
|
||||
expect(r.properties.task).to.eql(description.properties.title);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('resources.get()', function(){
|
||||
it('should get the resource', function(done) {
|
||||
resources.get({_id: description._id}, function (err, r) {
|
||||
expect(r).to.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('resources.del()', function(){
|
||||
it('should delete the resource', function(done) {
|
||||
resources.del({_id: description._id}, function (err, r) {
|
||||
resources.get({_id: description._id}, function (err, r) {
|
||||
expect(r).to.not.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
clean();
|
||||
|
||||
})
|
||||
|
||||
24
test/types.test.js
Normal file
24
test/types.test.js
Normal file
@@ -0,0 +1,24 @@
|
||||
var expect = require('chai').expect
|
||||
, client = require('../lib/client').use('http://localhost:3003')
|
||||
, dpd = require('../')
|
||||
, server = dpd('My Todo App')
|
||||
, types = client.use('/types')
|
||||
;
|
||||
|
||||
describe('GET /types', function(){
|
||||
it('should respond with a list of resource definitions', function(done) {
|
||||
types.get(function (err, types) {
|
||||
expect(types).to.eql({
|
||||
Collection: {
|
||||
defaultPath: '/my-objects'
|
||||
},
|
||||
UserCollection: {
|
||||
label: 'Users Collection',
|
||||
defaultPath: '/users'
|
||||
}
|
||||
});
|
||||
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user