chairo
chairo ("happy" in ancient Greek: χαίρω) is a Seneca micro-services plugin
for hapi. The plugin integrates the Seneca functionality into
hapi and provide tools to map its actions to server methods and views for easy access.
Lead Maintainer - Wyatt Preul
Usage
Plugin Registration
chairo is registered with a hapi server using the server.register()
method. Once
registered it decorates the server
object with a reference to the seneca
object initialized
using the provided plugin options. Default plugin options:
You can add a custom seneca
web plugin by passing in a function on the web
property. If web
is passed in, then the default web plugin for seneca is
disabled.
var Chairo = require('chairo');
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection();
server.register({ register: Chairo }, function (err) {
var id = 0;
server.seneca.add({ generate: 'id' }, function (message, next) {
return next(null, { id: ++id });
});
server.seneca.act({ generate: 'id' }, function (err, result) {
});
});
In addition, the hapi request object is decorated with a reference to the seneca
object for
easy access:
server.route({
method: 'POST',
path: '/id',
handler: function (request, reply) {
request.seneca.act({ generate: 'id' }, function (err, result) {
if (err) {
return reply(err);
}
return reply(result);
});
}
});
server.action(name, pattern, [options])
Maps a Seneca action pattern to a hapi
server method
where:
name
- the server method name (same as the name used in server.method()
).pattern
- the Seneca action pattern (e.g. 'generate:id'
or { generate: 'id' }
) to map.options
- optional settings options where:
cache
- method caching options (same as the name used in server.method()
).generateKey
- method generating custom cache key (same as the name used in server.method()
).
var Chairo = require('chairo');
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection();
server.register(Chairo, function (err) {
var id = 0;
server.seneca.add({ generate: 'id' }, function (message, next) {
return next(null, { id: ++id });
});
server.seneca.add({ calc: 'average' }, function (message, next) {
return next(null, { average: ( message.samples.dataset.values[0] + message.samples.dataset.values[0] ) / 2 });
});
server.action('generate', 'generate:id', { cache: { expiresIn: 1000, generateTimeout: 3000 } });
server.action('average', 'calc:average', { cache: { expiresIn: 1000, generateTimeout: 3000 } }, generateKey: function (message) {
return 'average-' + message.samples.dataset.values[0] + ':' + message.samples.dataset.values[1];
});
server.start(function () {
server.methods.generate(function (err, result1) {
server.methods.generate(function (err, result2) {
server.methods.average({ samples: { dataset: values: [2, 3] } }, function (err, avg1) {
server.methods.average({ samples: { dataset: values: [2, 3] } }, function (err, avg2) {
});
});
});
});
});
});
reply.act(pattern)
Sends back a handler response using the result of a Seneca action where:
pattern
- the Seneca action called to generate the response.
var Chairo = require('chairo');
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection();
server.register(Chairo, function (err) {
var id = 0;
server.seneca.add({ generate: 'id' }, function (message, next) {
return next(null, { id: ++id });
});
server.route({
method: 'POST',
path: '/id',
handler: function (request, reply) {
return reply.act({ generate: 'id' });
}
});
});
In addition, the act
handler shortcut is also provided:
server.route({
method: 'POST',
path: '/id',
handler: { act: 'generate:id' }
});
reply.compose(template, context, [options])
Renders a template view using the provided template and context where:
template
- the view engine template (same as the name used in
reply.view()
).context
- the context object used to render the template where each top level key with a $
suffix is assigned the corresponding Seneca action matching the key's value pattern.options
- optionals settings passed to reply.view()
.
var Chairo = require('chairo');
var Handlebars = require('handlebars');
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection();
server.register(Chairo, function (err) {
server.seneca.add({ lookup: 'date' }, function (message, next) {
return next(null, { date: (new Date()).toString() });
});
server.seneca.add({ load: 'user' }, function (message, next) {
return next(null, { name: message.name });
});
server.views({
engines: { html: Handlebars },
path: __dirname + '/templates'
});
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
var context = {
today$: 'lookup:date',
user$: { load: 'user', name: 'john' },
general: {
message: 'hello!'
}
};
return reply.compose('example', context);
}
});
});
Using the template ./templates/example.html
:
<div>
<h1>{{today$.date}}</h1>
<h2>{{user$.name}}</h2>
<h3>{{general.message}}</h3>
</div>
In addition, the compose
handler shortcut is also provided:
server.route({
method: 'POST',
path: '/id',
handler: {
compose: {
template: 'example',
context: {
today$: 'lookup:date',
user$: { load: 'user', name: 'john' },
general: {
message: 'hello!'
}
}
}
}
});