@apihawk/microcell v0.2.4
MicroCell
MicroCell is a toolkit for writing AppCell plugins.
Instalation
microcell is available on npm. To install it, type:
$ npm install @apihawk/microcellUsage
Import the library in your code and and choose the transport library you want to use:
const MicroCell = require('@apihawk/microcell');
const MicroCellAMQPTransport = require('@apihawk/microcell-amqp-transport');
const server = new (MicroCell.plugin(MicroCellAMQPTransport))();
server
.listen({
amqp_queue: process.ENV.AMQP_QUEUE,
amqp_url: process.ENV.AMQP_URL
})
.add({foo: 'One', bar: 'Two'}, (data, respond) => {
respond(null, `Payload is: ${data.payload}`);
})
.act({foo: 'One', bar: 'Two', payload: 'Hello World'}, () => {
console.log("Final response:", response); // Final response: Payload is: Hello World
});Modes
Server mode
The server mode is the most common mode of usage. In that mode, the app runs as a daemon and listens for instructions over the selected transport. It also supports actions (act) as the client mode.
const MicroCell = require('@apihawk/microcell');
const MicroCellAMQPTransport = require('@apihawk/microcell-amqp-transport');
const server = new (MicroCell.plugin(MicroCellAMQPTransport))();
server
.listen({
amqp_queue: process.ENV.AMQP_QUEUE,
amqp_url: process.ENV.AMQP_URL
})
.add({foo: 'One', bar: 'Two'}, (data, respond) => {
respond(null, `Payload is: ${data.payload}`);
})Client mode
The client mode executes all actions and exits after all of them get a response:
const MicroCell = require('@apihawk/microcell');
const MicroCellAMQPTransport = require('@apihawk/microcell-amqp-transport');
const client = new (MicroCell.plugin(MicroCellAMQPTransport))();
client
.client({
amqp_queue: process.ENV.AMQP_QUEUE,
amqp_url: process.ENV.AMQP_URL,
timeout: 2000 // Force exit after 2s
})
.act({foo: 'One', bar: 'Two', payload: 'Hello World'}, () => {
console.log("Final response:", response);
});Test mode
Test mode is for unit testing only. It does not require transport.
var Microcell = require('@apihawk/microcell');
var expect = require('chai').expect;
const Zones = require('../src/zones'); // Import some listeners (`add()`) from your module under test
describe('zones', () => {
const microcell = (new Microcell()).test().use(Zones);
it('create', done => {
expect(microcell).to.be.an('object');
microcell.act({resource: 'Zone', action: 'Create', _payload: 'secret data!'}, (err, result) => {
expect(err).to.be.null;
expect(result).to.be.an('object');
expect(result._payload).to.exist;
done();
});
});
});Methods
static plugin(plugin)
The plugin function allows extending of the library with plugins. It accepts a single parameter, which should be a MicroCell plugin. Returns the resulting class.
const MicroCell = require('@apihawk/microcell');
const MicroCellAMQPTransport = require('@apihawk/microcell-amqp-transport');
const client = new (MicroCell.plugin(MicroCellAMQPTransport))();listen(params)
The listen method starts a server that listens for JSON messages depending on the transport plugin. If you do not use a plugin, the function exits. Accepts params object which passes parameters for the used transport plugin. Returns the microcell object so that methods can be chained.
client(params)
On the client-side, calling microcell.client() means that MicroCell sends any actions it cannot match locally out over the selected transport.
Accepts params object which passes parameters for the used transport plugin. Returns the microcell object so that methods can be chained.
test()
Test mode is to run tests locally.
use(module, rule)
Loads module with add/act methods.
const Zones = require('./zones');
module.exports = function({
amqp_queue,
amqp_url
}) {
const server = new (MicroCell.plugin(MicroCellAMQPTransport))();
server
.use(Zones, {resource: 'Zone'})
.listen({
amqp_queue: amqp_queue,
amqp_url: amqp_url
});
};And in zones.js we have:
module.exports = function zones() {
this.add({action: 'Create'}, (msg, respond) => {
respond(null, { hello: 'create'});
});
this.add({action: 'Read'}, (msg, respond) => {
console.log("Read", msg);
respond(null, { hello: 'read' });
});
this.add({action: 'Update'}, (msg, respond) => {
respond(null, { hello: 'update' });
});
this.add({action: 'Delete'}, (msg, respond) => {
respond(null, { hello: 'delete' });
});
};The function accepts two parameters. The first is the module and the second is a rule to be matched for all the add methods in the module. rule is optional.
add(rules, callback)
Adds a listener for incoming actions. It accepts two parameters. rules is the rule to match and a callback is the function to execute on a match.
The callback has two parameters. msg is the data sent by the action together with the filtering rules. respond is a function to be called in response to the action. Accepts two parameters as follows: an error and a response data.
server.add({action: 'Delete'}, (msg, respond) => {
respond(null, { hello: 'delete' });
});act(data, callback)
act sends an action to a local or remote listener. It accepts two parameters. data is an object containing the rule parameters and the payload. Te callback is called on response with two parameters identical to the respond function of the add method. error and data.
client.act({
resource: 'Zone',
action: 'Read',
payload: { domain: 'exapmpe.com' }
}, (err, response) => {
console.log("Final response:", response);
});Tools
error(err | null,options)
Returns errors formatted in RFC 7807 - Problem Details for HTTP APIs format.
Parameters:
err- an Error object ornull.params- object with optional parameters:code- status code. Type:stringDefault value:'500'message- error message. Type:string. Default value:'Internal server error'detail- error details. Type:string. Default value:err.messagerequest- original request data. TypeObjectstack- error stack trace. Type:stringorObject. Default value:err.stackvalidation_messages- messages on validation errors. Type:Array<string>original_error- The original error if any. Type:stringorObject.
respond(this.error(new Error('Something went wrong!'), {
message: 'Service is temporarly unavailable',
code: '503'
}));validationError(err | null,options)
Same as error but the default values for params.code and params.messages are '422' and 'Validation failed'.
respond(this.validationError(null, {validation_messages: errors}), null);validate(data, schema)
Validates a data object against a JSON Schema.
const errors = this.validate(data.id, {'type': 'number'});
if (errors.length) {
respond(this.validationError(null, {validation_messages: errors}), null);
return;
}validateHttpResponse(err, response)
Turns HTTP errors (4xx, 5xx) into API Problem errors. Parameters:
err- an Error object.response- a http.IncomingMessage object.
request.delete({
url: `${api_base}/dns_zones/${ data.id }.json`,
auth: auth
}, (err, response) => {
const httpError = this.validateHttpResponse(err, response);
if (httpError) {
respond(httpError);
return;
}
respond(null, this.formatResponse());
});formatResponse(body,params)
Returns a JavaScript object which includes response body, title and status. The returned object can be for a response.
body- A JavaScript Object to respond withparams- object with optional parameters:code- status code. Type:stringDefault value:'200'title- error title. Type:string. Default value:OK
respond(null, this.formatResponse({foo: "bar"})); // {title:'OK',status:'200',response:{foo:'bar'}}License
Copyright (c) 2019 Anton Katsarov and other contributors; Licensed under MIT.