autobahnjs
deepjs/server oriented tools and middlewares for expressjs.
Autobahnjs comes with two kind of tools :
- middlewares for expressjs
- context : assign context to each incoming request
- modes : assign modes (ocm related) to each incoming request (based on current session)
- restful : map-to-service middleware (HTTP/rest dynamic routing)
- html : map-to-html middleware (deep-views/routes render map)
- statics : map-to-files middleware (dynamic map for statics files server)
- login : retrieve matched user and hold user in current session.
- logout : break current session.
- "App" object definition and tools for session/user management through deepjs chained API.
install
As autobahnjs is an environnement that tie a bunch of tools together and should be piloted from your own index.js :
You should use the yeoman autobahnjs generator to get a workable structure.
coming really soon.
Or simply use the example folder, provided in autobahn lib under autobahnjs/lib.
when you're in (after clone or npm install) :
npm install
node index.js
Enjoy.
Example of autobahnjs "app" and expressjs skeleton
var deep = require("deepjs"),
express = require('express'),
autobahn = require("autobahnjs"),
Unit = require("deepjs/lib/unit");
var cookieParser = require('cookie-parser');
var session = require('express-session');
var bodyParser = require('body-parser');
deep.Validator.set(require("deepjs/lib/schema"));
deep.globals.rootPath = __dirname;
deep.context("cwd", __dirname);
deep.Modes({
roles:"public"
});
var app = express();
var autobahnApp = autobahn.app({
port:3000,
initContext: function(context){
return context;
},
loggedIn: function(session) {
session.myDecoration = true;
return session;
},
sessionModes: function(session)
{
if (session && session.user)
return { roles: "user" };
else
return { roles: "public" };
},
loginConfig: {
store: "user",
encryption: "sha1",
loginField: "email",
passwordField: 'password'
}
}, app);
app
.use(cookieParser())
.use(session({
resave:false,
saveUninitialized:true,
secret: 'paezijp7YlhgiGOUYgtogz',
maxAge: new Date(Date.now() + 3600000)
}))
.use(bodyParser.json({ strict:false, extended:true }))
.use(autobahn.context.middleware(autobahnApp.initContext))
.use(autobahn.modes.middleware(autobahnApp.sessionModes))
.post("/logout", autobahn.logout.middleware())
.post("/login", autobahn.login.middleware(autobahnApp))
.use(autobahn.restful.map(YOUR_SERVICES_MAP))
.use(autobahn.html.map(YOUR_HTML_MAP))
.use(autobahn.statics.middleware(YOUR_STATICS_MAP))
.use(function(req, res, next) {
console.log("nothing to do with : ", req.url);
res.writeHead(404, {
'Content-Type': 'text/html'
});
res.end("error : 404");
})
.listen(autobahnApp.port);
deep.App(autobahnApp);
console.log("server is listening on port : ", autobahnApp.port);
var repl = require("repl")
.start({
prompt: "node via stdin> ",
input: process.stdin,
output: process.stdout
});
Example of restful map
For full info on how managing/designing restful stores, see deep-restful and deepjs core documentation.
var deep = require("deepjs/deep");
require("deep-mongo");
module.exports = {
"/user": deep.ocm({
admin: deep.Mongo(null, "mongodb://127.0.0.1:27017/testdb", "user"),
user: {
backgrounds: ["this::../admin", deep.Disallow("del", "flush")]
},
"public": {
backgrounds: ["this::../user", deep.AllowOnly("get")]
}
}, {
protocol: "user",
sensibleTo: "roles"
}),
"/foo":deep.Collection("foo", [{ id:"e1", bar:true, zoo:"hello world" }])
};
Example of html map
For full info on how managing/designing html routes map, see deep-views and deep-routes documentation.
var deep = require("deepjs");
require("deep-views/lib/view");
require("deep-node/lib/rest/file/json")({
protocol: "json",
basePath: "/www"
});
require("deep-swig/lib/nodejs")({
protocol: "swig",
basePath: "/www"
});
module.exports = {
head:deep.View({
how:"<title>html from server</title>",
where:"dom.appendTo::head"
}),
index:deep.View({
how:"swig::/app.html",
where:"dom.appendTo::",
subs:{
topbar:deep.View({
how:"<div>topbar</div>",
where:"dom.htmlOf::#topbar"
}),
content:deep.View({
route:"/$",
how:"<div>default content</div>",
where:"dom.htmlOf::#content"
}),
hello:deep.View({
route:"/hello/?s:name",
how:"<div>hello { name+'!' | 'dude!'}</div>",
where:"dom.htmlOf::#content"
})
}
})
};
Example of statics map
var deep = require("deepjs/deep");
module.exports = {
"/": [{
path: deep.globals.rootPath + '/www',
options: {
maxAge: 86400000,
redirect: false
}
}]
};
Usage from outside.
Outside means from you prefered http client (maybe your browser) to the server.
If you use previous map in your autobahnjs/express skeleton (as above) :
Open your browser and try by example :
http://127.0.0.1:3000/
http://127.0.0.1:3000/hello
http://127.0.0.1:3000/hello/jhonny
http://127.0.0.1:3000/foo
http://127.0.0.1:3000/foo/e1
http://127.0.0.1:3000/foo/?bar
...
And with your prefered restful client, you should try to post/put/patch/del/get/range/... to /foo service.
Usage from "inside"
Inside means from nodejs CLI or from any script executed server side.
- deep.App(appObj) : holds appObj as main app accessible through chains.
- deep.login({ email:"john@doe.com", password:"test123"}) : start a contextualised chain, create session, retrieve user, etc. exactly as if you had really logged in from outside (i.e. through http client)
- .login(...) : from anywhere in a chain, do the same thing than deep.login
- deep.impersonate({ id:"..." }) : start a contextualised chain, rerieve user an do login without password.
- .impersonate(...) : from anywhere in a chain, do the same than deep.impersonate
- .logout() : : from anywhere in a chain, break current session
example :
deep.App(appObj);
deep.login({ email:"john@doe.com", password:"..." })
.restful("myCollection")
.put({ })
.logout()
.impersonate({ id:"some_user_id" })
.restful("someCollection")
.get("?email=ced@doe.com")
.done(function(s){ })
.fail();
deepjs core provides additionnaly the .modes(...)
API that allow you, by example, to do :
deep.modes({ roles:"admin" }).restful("user").get().log();
Manage multiple app (advanced)
Imagine that you produce different expressjs skeleton/autobhan js app in the same nodejs process.
You should want to switch from one to another and/or execute each in its own context.
For that you have two method that encapsulate the provided app in chain context.
- deep.app(appObj) : start a contextualised chain that hold appObj in its context. (advanced)
- .app(appObj) : from anywhere in a chain, hold appObj in its context. (advanced)