@apihawk/microcell

0.2.4 • Public • Published

MicroCell

MicroCell is a toolkit for writing AppCell plugins.

Instalation

microcell is available on npm. To install it, type:

$ npm install @apihawk/microcell

Usage

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 or null.
  • params - object with optional parameters:
    • code - status code. Type: string Default value: '500'
    • message - error message. Type: string. Default value: 'Internal server error'
    • detail - error details. Type: string. Default value: err.message
    • request - original request data. Type Object
    • stack - error stack trace. Type: string or Object. Default value: err.stack
    • validation_messages - messages on validation errors. Type: Array<string>
    • original_error - The original error if any. Type: string or Object.
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:

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 with
  • params - object with optional parameters:
    • code - status code. Type: string Default 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.

Readme

Keywords

none

Package Sidebar

Install

npm i @apihawk/microcell

Weekly Downloads

5

Version

0.2.4

License

MIT

Unpacked Size

24 kB

Total Files

7

Last publish

Collaborators

  • pavkatar
  • palazliev
  • tsvetan-ganev
  • a-katsarov