asyncapi-sub-middleware

1.0.3 • Public • Published

asyncapi-sub-middleware

Create routes and validation for an express-like async server

Summary

This module will automatically adds parameters, headers and message validators to your express-like async application (see kafka-express or rabbitmq-express) from an AsyncAPI definition file. It will also mount your own middlewares if asked.
Freely inspired by swagger-tools

Usage

const rabbitserver = require('rabbitmq-express');
const asyncApi = require('asyncapi-sub-middleware');

const app = rabbitserver();

const doc = fs.readFileSync('./lib/myAsyncAPIFile.yaml', 'utf8');

await asyncApi(app, doc, { stubMiddleware: true });

app.listen(options);

This will validate and parse your AsyncAPI file (myAsyncAPIFile.yaml), then create a route for each channel with a publish operation defined in that file. The validation and parsing of the file is done by @asyncapi/parser.
This route will validate the parameters of the route and the headers and body of the message with the parameter, headers and payload schemas defined in the file and add them to the api property of the request object. The validation itself is done by ajv.
It will then add a "stub" middleware on each route.

Documentation

asyncapi-sub-middleware

The module exports a function that takes your express-like application, an AsyncAPI document and options.

require('asyncapi-sub-middleware')(application, document, options)

application

Any application using middlewares can be used, i.e. there should be a .use(route, [middlewares]) function available.
The request object fed into the middlewares should have a params and a body property to validate against the schema.
The application is responsible for the connection to the actual async server (rabbitmq, kafka, etc...)

document

The AsyncAPI file. It accepts 3 formats:

string (reading directly from the file)

const document = fs.readFileSync('./lib/myAsyncAPIFile.yaml', 'utf8');

JSON (the file converted to a JSON object)

const yaml = require('js-yaml');
const document = yaml.load(fs.readFileSync('./lib/myAsyncAPIFile.yam', 'utf8'));

AsyncAPIDocument (the file parsed through @asyncapi/parser)

const { parse } = require('@asyncapi/parser');
const document = await parse(fs.readFileSync('./lib/myAsyncAPIFile.yam', 'utf8'));

options

An optional object. All properties are optional too.

// these are the default values
const {
  tag = '',
  requireController = true,
  controllers = '',
  stubMiddleware = false,
} = options;

If tag is set, only the tagged publish operations will be mounted.
If requireController is set to false, only the 2 validation middlewares will be mounted and all controller's related infos will be ignored.
controllers should be the path to a directory/file defining the controller middlewares for each publish operations.
If stubMiddleware is set to true, a stub middleware will be mounted on each route if a controller middleware is not defined.

ValidationError

The module exports the error class that is thrown in case of a validation error.

const { ValidationError } = require('asyncapi-sub-middleware');
if (err instanceof ValidationError) // That's our error.

Controller Middleware

To be able to automatically mount your controller middlewares you need to provide a combination of information.

First, in the options object requireController should be set to true (it is the default.)

Second, you need to provide the path to one or more files containing your middlewares. For that we use the controllers property of the options object and an optional extension in the AsyncAPI file on the publish operation:

x-operation-controller

Third, you need to define the operationId of the publish operation as the name of a function on the file defined by the combination of the controllers and the x-operation-controller.

example

The options object:

const options = {
  tag = 'myApp',
  requireController = true,
  controllers = 'src/api',
  stubMiddleware = false,
};

The AsyncAPI file:

channels:
  topic.{id}.key:
    parameters:
      id:
        $ref: '#/components/parameters/myid'
    publish:
      tags:
        - name: myApp
      operationId: nameOfMyMiddleware
      x-operation-controller: 'topic/myControllerFile'
      message:
        $ref: '#/components/messages/mymessage'

In this example you should have a "required-able" file on the path defined by the combination of controllers and the x-operation-controller, i.e. src/api/topic/myControllerFile.js.
This file should export a function by the name of the operationId, i.e nameOfMyMiddleware

The controller file for this operation (src/api/topic/myControllerFile.js):

module.exports = {
  nameOfMyMiddleware: (req, res, next) => {
    const { api: { params, headers, body } } = req;
    //do something
  }
}

OR

module.exports = {
  nameOfMyMiddleware: () => {
    return [
      (req, res, next) => {
        const { api: { params, headers, body } } = req;
        //do something
      },
      (err, req, res, next) => {
        //do something in case of an error
      }
    ]
  }
}

Package Sidebar

Install

npm i asyncapi-sub-middleware

Weekly Downloads

0

Version

1.0.3

License

MIT

Unpacked Size

43.7 kB

Total Files

19

Last publish

Collaborators

  • cleareyesfullhearts