Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@financialforcedev/orizuru

financialforcedev318BSD-3-Clause9.3.2TypeScript support: included

Streamlined communication between Heroku dynos / other worker processes

webhook, web, heroku, worker, orizuru, dyno

readme

Orizuru

Build Status

Orizuru is a library that streamlines strongly typed communication between Heroku dynos (or other processes). It leverages Apache Avro for schema validation and communication.

Install

npm install @financialforcedev/orizuru

Usage

Configuration

All Orizuru classes require reference to a transport layer. The transport layer governs how messages are published and subscribed. We inject this as a class constructor configuration parameter.

import { Server } from '@financialforcedev/orizuru';
import { Transport } from '@financialforcedev/orizuru-transport-rabbitmq';

const transport = new Transport({
    url: 'amqp://localhost'
});

const server = new Server({
    port: 8080,
    transport
});

The example above shows how to use our RabbitMQ transport layer with a Server. The same method is used with our other classes.

Server

A Orizuru Server allows you combine Avro schemas with API POST endpoints to create webhooks that validate API post body content and publish events via your chosen transport layer implementation. POST bodies are automatically validated against the Avro schema they are paired with, so the consumer of your events always receives valid input if it is invoked.

import { json, Server } from '@financialforcedev/orizuru';
import { Transport } from '@financialforcedev/orizuru-transport-rabbitmq';

const schema = {
    name: 'ageAndDob',
    type: 'record',
    fields: [
        { name: 'age', type: 'string' },
        { name: 'dob', type: 'string' }
    ]
};

const transport = new Transport({
    url: 'amqp://localhost'
});

const server = new Server({
    port: 8080,
    transport
});

server.addRoute({
    endpoint: '/api/path/',
    middleware: [
        json()
    ],
    schema
})

server.listen();

In the above example, a POST API for /api/path/ageAndDob is created on the server before it listens on port 8080. The post body sent is validated against the schema, which requires age and dob string fields in the JSON body. If the validation succeeds, an event name passed to the transport layer will be the fully qualified name of the Avro schema type ageAndDob, along with an Avro serialised buffer of the POST body.

Additionally, if there is an object on the request called orizuru, e.g. request.orizuru, this will also be serialized and added to the buffer as context. This allows middleware to add context information to the event fired, e.g. session validation and credentials.

Publisher

The Orizuru Publisher allows you to publish events directly from Node.js via a transport layer, with Avro. This can be useful for communication between worker processes that do not expose a Web API. Messages are validated against a supplied schema, and there is also the facility to supply untyped context information.

import { IOrizuruMessage, Publisher } from '@financialforcedev/orizuru';
import { Transport } from '@financialforcedev/orizuru-transport-rabbitmq';

interface Message {
    age: string;
    dob: string;
}

interface Context extends Orizuru.Context {
    sessionId: string;
}

const schema = {
    namespace: 'foo',
    name: 'bar',
    type: 'record',
    fields: [
        { name: 'age', type: 'string' },
        { name: 'dob', type: 'string' }
    ]
};

const message: IOrizuruMessage<Context, Message>  = {
    context: {
        sessionId: '​​​​​9B055039660429865FD49FE65E7FEC4A89F9D20C5D398957C71AFF41091CC276​​​​​'
    },
    message: {
        age: 'fifty',
        dob: '07/01/1991'
    }
};

const transport = new Transport({
    url: 'amqp://localhost'
});

const publisher = new Publisher({
    transport
});

publisher.publish({ schema, message });

This example publishes an event named foo.bar with the message described. The message part is validated against the schema. The context object extends the Orizuru.Context interface, in this case containing a session id.

Handler

The handler handles messages published by the Server or Publisher. It requires a schema name and a handler.

NOTE: The supplied callback to this handler should always handle errors. This means it should never throw an exception, and any promise it returns should always have a catch block. Any errors thrown / rejecting promises returned will be swallowed.

import { Handler, IOrizuruMessage } from '@financialforcedev/orizuru';
import { Transport } from '@financialforcedev/orizuru-transport-rabbitmq';

const schema = {
    namespace: 'foo',
    name: 'bar',
    type: 'record',
    fields: [
        { name: 'age', type: 'string' },
        { name: 'dob', type: 'string' }
    ]
};

const handler = async ({ message, context }: IOrizuruMessage<any, any>) => {
    console.log('handling messages from the server API');
    console.log(message);
    console.log(context);
}

const transport = new Transport({
    url: 'amqp://localhost'
});

const handlerInstance = new Handler({
    transport
})

Promise.all([
    handlerInstance.handle({ schema, handler })
]);

The handler can handle multiple events, with callbacks for each wired in. The input to the callback { message, context } is auto deserialized, so you get the JS object represention of the API post body or the JS object published, along with the context added by server middleware or supplied to the publish function.

API Docs

Click to view TSDoc API documentation.

changelog

@financialforcedev/orizuru

9.3.2

OTHER CHANGES

  • Use the Docker image from Orizuru-Transport-RabbitMQ for the system tests
  • Add Docker scripts to the package.json that:
    • Build the orizuru-transport-rabbitmq--rabbitmq service
    • Start the orizuru-transport-rabbitmq--rabbitmq service
    • Cleanup the created container and image
    • Start the service then run the system tests
  • Remove the RabbitMQ service from the Travis configuration
  • Amalgamate the change log files

9.3.1

  • Rework and complete documentation
  • Convert to using Jest for testing

9.3.0

  • Updated IHandler, IPublisher and IServer interfaces to extend EventEmitter
  • Added support for ErrorRequestHandler as middleware

9.2.0

  • Update typescript configuration to target es2017

9.1.0

  • Export the RequestHandler from express
  • Export the ResponseWriter type
  • Update the IServer, IPublisher and IHandler types to include the missing functions
  • Update the lodash imports and use es2017 functions where appropriate
  • Update tests for changes to sinon
  • Remove fs-extra dependency
  • Remove the npmignore file and update the package.json to package the correct files
  • Remove the properties files

9.0.1

  • Update all dependencies to latest versions
  • Remove all references to new Buffer()
    • Use Buffer.from() instead to remove deprecation warnings

9.0.0

  • The addRoute method can now add synchronous APIs
    • Set the synchronous property to true in the route options to do this
    • All incoming messages are still validated against the Apache Avro schema but are not published to a message queue
    • The validated request is stored in the body property of the request
    • Synchronous request logic should be added to the responseWriter property
  • The routing mechanism for Orizuru has been updated so that each endpoint now uses a different express router
  • Orizuru now expects a class for the transport layer
    • Each server, publisher and handler should have a different transport instance
    • The configuration for the transport can be provided in the constructor
    • Updated ITransport interface
    • Removed Orizuru.Transport.IConnect interface
  • Addition of helper methods for listen, close, set and use to the Orizuru Server
    • By default, close also closes the transport layer
    • By default, listen starts the server listening for connections specified in the Options
  • All Orizuru Handler and Publisher instances must now be initialised by calling the init() function. This initialises the connection
  • The getPublisher and getServer functions have been replaced with property getters
  • Added Orizuru.Message interface to the IOrizuruMessage

    • This acts as the base interface for all messages sent by Orizuru
  • Events have now been converted to use symbols

  • Add system tests to test core functionality
    • Addition of RabbitMQ docker image using the same version as Travis CI
    • System test coverage is now included in Travis builds
  • Add nyc.opts file to clean up the package.json

  • Fix a regression where the context Avro schema could contain anonymous types

  • Documentation is now generated using the master branch for definition links

8.0.2

FIXES

  • Default the event name to the schema name when publishing a message

8.0.1

FIXES

  • Make sure that messages can be published if the context is empty

8.0.0

BREAKING CHANGES

  • Use generic types for the IOrizuruMessage
    • This will cause compile time errors even though there are no functional changes

NEW FEATURES

  • Add use and set functions to the server
  • Export static function from express in the index

7.1.1

FIXES

  • Update all validators to allow for transport objects created by constructors other than Object

7.1.0

NEW FEATURES

  • Allow for transport objects created by constructors other than Object

7.0.0

OTHER CHANGES

  • Conversion to Typescript

6.1.1

OTHER CHANGES

  • Fix security advisories
  • Relax versioning

6.1.0

NEW FEATURES

  • Allow customisation of the mapping from Avro schema namespace to URL path

6.0.1

FIXES

  • Make the subscribe handler wrapper async, and await the inner handler

6.0.0

BREAKING CHANGES

  • The server addRoute method has been updated to add each route separately
  • The server addGet method has been removed
    • The addRoute allows you to specify the method as part of the route configuration
  • The Server, Publisher and Handler now extend EventEmitter
    • Any cases of Server.emitter, Publisher.emitter and Handler.emitter should be changed to reference the instance

NEW FEATURES

  • Added the npm init-project command.
    • This command should be called before running any of the examples. It makes a local copy of the run.properties and test.properties files

OTHER CHANGES

  • The transport schema has been updated to an Apache Avro schema (.avsc) file
  • Updated the JS documentation to use the Minami theme
  • Removed the jsbeautifyrc file
    • We now use the beautify file specified in the eslint-config package