This commit is contained in:
Ritchie Martori 2013-04-09 09:02:36 -07:00
commit 2a0f68e434
21 changed files with 391 additions and 0 deletions

10
.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
.DS_Store
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.swp
*.swo
node_modules/

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# asteroid
v0.0.1
## Install
slnode install asteroid
## Example
var Asteroid = require('asteroid');
var asteroid = Asteroid.create();
asteroid.myMethod();

View File

@ -0,0 +1,8 @@
var asteroid = require('../../');
var app = asteroid();
app.get('/', function (req, res) {
res.send('hello world');
});
app.listen(3000);

View File

@ -0,0 +1,7 @@
var asteroid = require('../../');
var app = asteroid();
app.use(asteroid.configure());
app.use(asteroid.resources());
app.listen(3000);

View File

@ -0,0 +1,8 @@
{
"module": "resource",
"options": {
"path": "/example-resource",
"msg": "my message?"
},
"main": "example.js"
}

View File

@ -0,0 +1,14 @@
// any module instance can be required by its directory
var exampleResource = require('.');
// exampleResource.app is an express sub app
// anything registered (routes, middleware)
// will only run relative to the defined root
// '/' resolves to '/example-resource'
exampleResource.app.get('/', function (req, res) {
res.send(exampleResource.options.msg + '??????');
});
exampleResource.app.get('/foo', function (req, res) {
res.send('foo!!!');
});

7
example/todos/app.js Normal file
View File

@ -0,0 +1,7 @@
var asteroid = require('../../');
var app = asteroid();
app.use(asteroid.configure());
app.use(asteroid.resources());
app.listen(3000);

View File

@ -0,0 +1,12 @@
{
"production": {
"module": "mongo",
"options": {
"database": "todos",
"port": 5555,
"host": "remote.db.com",
"username": "foo",
"password": "bar"
}
}
}

View File

@ -0,0 +1,11 @@
{
"module": "data-store",
"options": {
"database": "asteroid-examples-todos",
"port": 27017,
"host": "127.0.0.1"
},
"dependencies": {
"db": "memory"
}
}

View File

@ -0,0 +1,9 @@
{
"module": "collection",
"options": {
"path": "/todos"
},
"dependencies": {
"model": "todos-model"
}
}

View File

@ -0,0 +1,22 @@
{
"module": "model",
"options": {
"properties": [
{
"name": "title",
"type": "string"
},
{
"name": "done",
"type": "boolean"
},
{
"name": "order",
"type": "number"
}
]
},
"dependencies": {
"data-store": "db"
}
}

View File

@ -0,0 +1,43 @@
var todos = require('.');
todos.app.get('/completed', function (req, res) {
todos.store.all({where: {creator: req.me, done: true}}, todos.done);
});
todos.on('before:validate', function (todo, ctx) {
if(!todo.name) {
throw new Error('name is required');
}
if(todo.name.length > 144) {
ctx.error('name must be shorter than 144 characters');
}
});
todos.on('before:create', function (todo, ctx, done) {
ctx.errorUnless(ctx.isEmail(todos.creator));
todos.model.count({owner: todo.owner}, function (err) {
if(err) {
done(err);
} else {
ctx.errorIf(count > 100, 'each user can only have 100 todos');
done();
}
});
});
todos.on('query', function (query, ctx) {
ctx.cancelUnless(query.creator);
query.$limit = query.$limit || 16;
ctx.errorIf(query.$limit > 16, 'todos can only include a maximum of 16 results');
});
todos.on('modify', function (todo, ctx) {
ctx.cancelUnless(ctx.isMe(todo.creator));
});
todos.on('request', function (ctx) {
ctx.cancelUnless(ctx.me);
});

View File

@ -0,0 +1,20 @@
{
"module": "users-collection",
"options": {
"root": "/users",
"name": "users",
"properties": [
{
"name": "email",
"type": "string"
},
{
"name": "password",
"type": "password"
}
]
},
"dependencies": {
"store": "store"
}
}

5
index.js Normal file
View File

@ -0,0 +1,5 @@
/**
* asteroid ~ public api
*/
module.exports = require('./lib/asteroid');

76
lib/asteroid.js Normal file
View File

@ -0,0 +1,76 @@
/**
* Module dependencies.
*/
var express = require('express')
, fs = require('fs')
, path = require('path')
, utils = express.utils;
/**
* Expose `createApplication()`.
*/
var asteroid = exports = module.exports = createApplication;
/**
* Framework version.
*/
asteroid.version = require('../package.json').version;
/**
* Expose mime.
*/
asteroid.mime = express.mime;
/**
* Create an asteroid application.
*
* @return {Function}
* @api public
*/
function createApplication() {
var app = express();
app.disuse = function (route) {
if(this.stack) {
for (var i = 0; i < this.stack.length; i++) {
if(this.stack[i].route === route) {
this.stack.splice(i, 1);
}
}
}
}
return app;
}
/**
* Expose express.middleware as asteroid.*
* for example `asteroid.errorHandler` etc.
*/
for (var key in express) {
Object.defineProperty(
asteroid
, key
, Object.getOwnPropertyDescriptor(express, key));
}
/**
* Expose additional asteroid middleware
* for example `asteroid.configure` etc.
*/
fs.readdirSync(path.join(__dirname, 'middleware')).forEach(function (m) {
asteroid[m.replace(/\.js$/, '')] = require('./middleware/' + m);
});
/**
* Error handler title
*/
asteroid.errorHandler.title = 'Asteroid';

View File

@ -0,0 +1,25 @@
/**
* Module dependencies.
*/
var ModuleLoader = require('module-loader');
/**
* Export the middleware.
*/
module.exports = configure;
/**
* Load application modules based on the current directories configuration files.
*/
function configure(root) {
var moduleLoader = ModuleLoader.create(root || '.');
return function configureMiddleware(req, res, next) {
req.modules = res.modules = moduleLoader;
moduleLoader.load(next);
}
}

View File

@ -0,0 +1,25 @@
/**
* Module dependencies.
*/
var ModuleLoader = require('module-loader');
/**
* Export the middleware.
*/
module.exports = middleware;
/**
* Load application modules based on the current directories configuration files.
*/
function middleware() {
var modules = this.modules;
return function executeAsteroidMiddleware(req, res, next) {
// TODO implement asteroid specific middleware stack
next();
}
}

View File

@ -0,0 +1,32 @@
/**
* Module dependencies.
*/
var asteroid = require('../asteroid');
/**
* Export the middleware.
*/
module.exports = resources;
/**
* Build a temp app for mounting resources.
*/
function resources() {
return function (req, res, next) {
// xxx - cache the temp app and only build when modules change?
var tempApp = asteroid();
var resources = req.modules.instanceOf('Resource');
// mount all resources
resources.forEach(function (r) {
r.mount(tempApp);
});
tempApp.handle(req, res, next);
}
}

15
package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "asteroid",
"description": "asteroid",
"version": "0.0.1",
"scripts": {
"test": "mocha"
},
"dependencies": {
"debug": "latest",
"express": "~3.1.1"
},
"devDependencies": {
"mocha": "latest"
}
}

24
test/asteroid.test.js Normal file
View File

@ -0,0 +1,24 @@
var Asteroid = require('../');
describe('Asteroid', function(){
var asteroid;
beforeEach(function(){
asteroid = new Asteroid;
});
describe('.myMethod', function(){
// example sync test
it('should <description of behavior>', function() {
asteroid.myMethod();
});
// example async test
it('should <description of behavior>', function(done) {
setTimeout(function () {
asteroid.myMethod();
done();
}, 0);
});
});
});

5
test/support.js Normal file
View File

@ -0,0 +1,5 @@
/**
* asteroid test setup and support.
*/
assert = require('assert');