Express.js application bootstrapper. Simplicity, brevity, flexibility.
npm i bex --save
var config = require('./config').web;
var ong = require('ong').init();
require('bex').createApp({
basedir: __dirname,
bodyParser: { limit: '1mb' },
viewEngine: require('express-dot').__express,
hooks: { after: initialize }
}).listen(config.port);
function initialize (app) {
ong.register('db', require('knex')(config.db));
ong.register(this.requireAll(__dirname + '/modules'));
}
module.exports = {
create: _.flow($.sanitize, $.validate, $.authorize, function (params) {
return $.db('items').insert(params).then(this.json);
}),
'&/:id/render': function (params) {
return Promise
.props({ item: $.db('items').where('id', params.id).first() })
.then(_.partial(this.view, 'items/index'));
},
'PUT items/:id/star': _.flow($.authorize, function (params) {
return $.db('items').where('id', params.id).update('is_starred', 1).then(this.json);
})
};
As you probably noted, there are 2 ways of specifying the route-handler pair:
- implicit: via method names like
list
(GET resource
),view
(GET resource/:id
),create
(POST resource
),update
(PUT resource/:id
) andremove
(DELETE resource/:id
) - explicit: by specifying exact route (
GET resource/:from/:to
) or exact route with resource name placeholder (GET &/:id
) where kebab-cased controller's name will be substituted
In case of explicit route, you can omit GET
verb, it is being used by default (&/:id
is the same as GET &/:id
or get &/:id
).
- creates
express.js
app - calls hook (
before
), if it is passed viahooks
param - sets
'trust proxy'
totrue
(very oftennode.js
app is hosted behindnginx
) - initializes view-related stuff, can be omitted by specifying
views: false
- initializes
body-parser
(almost everyexpress.js
-based project needs this) - creates router based on controllers modules (see example), can be omitted, if no
controllers
param is passed - calls hook (
after
), if it is passed viahooks
param
- it is expected, that route handler returns view result (or promise with view result):
return this.json({ my: 'data' });
- there are 3 built-it view results:
view(name, data)
(ends with rendering ofname
view withdata
),redirect(url)
andjson(data)
- you can register your own result, which will be available via
this
inside route handler:bex.registerResult('myresult', function (anyarg) { return { type: 'myresult', arg: anyarg }; });
- minimal requirement for result constructor is to return result object with mandatorytype
property - you can register your own result handler, which will be called once result of given
type
is obtained from any of your route handlers:bex.registerHandler('myresult', function (req, res, result) { res.send(result.anyarg); });
There are 2 special results
exception
- generated when exception occurs inside route handler (default handler will cause empty response with500
code)undefined
- generated when no view result is returned from route handler (its default handler will cause empty response with404
status)
You can override how bex
reacts to these 2 special results (as well as other "ordinary" results) via overwriting their handlers: bex.registerHandler('exception', function (req, res, exception) { logstash.send(req.url, exception); }, true);
.
- there are 2 hooks:
before
(called just afterexpress.js
app is created, but nothing was performed with it) andafter
(called after everything is done andbex
is ready to return bootstrapped app) - each hook will have
this
populated with utility methods:requireAll
,registerResult
,registerHandler
,createRouter
Requires all modules which exist inside specified folder (see require-all docs for details).
Registers view result(s).
Registers view result handler(s).
Loads everything from specified path
and maps converts to route-handler pairs, applying them to express.Router
. Returns express.Router
instance ready to be used by express.js
app. Also accepts object as argument, each property-value of which will be treated as controllerName
-controllerInstance
pairs.
MIT