z0mt3c / hapi-swaggered

Yet another hapi plugin providing swagger compliant API specifications based on routes and joi schemas to be used with swagger-ui.
MIT License
82 stars 38 forks source link

hapi-swaggered 3.x

Yet another hapi plugin providing swagger compliant API specifications (swagger specs 2.0) based on routes and joi schemas to be used with swagger-ui.

Supports hapi 17.x and up

For earlier versions check hapi-swaggered 2.x (current default/latest npm install hapi-swaggered --save)

Build Status Coverage Status js-standard-style npm downloads

Install

npm install hapi-swaggered@next --save

Similar swagger-projects for hapi

krakenjs/swaggerize-hapi follows a design driven approach (swagger-schema first) for building APIs. In other words: it supports you to implement an api behind a specific swagger-schema while you have to create and maintain the swagger-schema yourself (or a third-party). In contrast with hapi-swaggered you will have to design your api through hapi route defintions and joi schemas (or did already) and hapi-swaggered will generate it's swagger specifications up on that (Of course not as beautiful and shiny structured as done by hand). Based on this you are able to get beautiful hands-on swagger-ui documentation (like this) for your api up and running (e.g. through hapi-swaggered-ui).

Swagger-UI

This plugin does not include the swagger-ui interface. It just serves a bare swagger 2.0 compliant json feed. If you are looking for an easy swagger-ui plugin to drop-in? You should have a look at:

Plugin Configuration

Example

Example configuration for hapi-swaggered + hapi-swaggered-ui

const Hapi = require('hapi');

(async () => {
  const server = await new Hapi.Server({
    port: 8000
  })

  await server.register([
    require('inert'),
    require('vision'),
    {
      plugin: require('hapi-swaggered'),
      options: {
        tags: {
          'foobar/test': 'Example foobar description'
        },
        info: {
          title: 'Example API',
          description: 'Powered by node, hapi, joi, hapi-swaggered, hapi-swaggered-ui and swagger-ui',
          version: '1.0'
        }
      }
    },
    {
      plugin: require('hapi-swaggered-ui'),
      options: {
        title: 'Example API',
        path: '/docs',
        authorization: {
          field: 'apiKey',
          scope: 'query', // header works as well
          // valuePrefix: 'bearer '// prefix incase
          defaultValue: 'demoKey',
          placeholder: 'Enter your apiKey here'
        },
        swaggerOptions: {
          validatorUrl: null
        }
      }
    }
  ])

  server.route({
    path: '/',
    method: 'GET',
    handler (request, h) {
      return h.response().redirect('/docs')
    }
  })

  try {
    await server.start()
    console.log('Server running at:', server.info.uri)
  } catch (err) {
    console.log(err)
  }
})()

Demo Routes

server.route({
  path: '/foobar/test',
  method: 'GET',
  options: {
    tags: ['api'],
    description: 'My route description',
    notes: 'My route notes',
    handler () {
      return {};
    }
  }
});

server.route({
  path: '/foobar/{foo}/{bar}',
  method: 'GET',
  options: {
    tags: ['api'],
    validate: {
      params: {
        foo: Joi.string().required().description('test'),
        bar: Joi.string().required()
      }
    },
    handler () {
      return {};
    }
  }
});

Features

Model naming

To assign custom names to your Models use the Joi.meta() option (in previous joi versions Joi.options() may be used)

Joi.object({}).meta({ className: 'FooBar' });

Model description

To assign a description to your Models use the Joi.meta() option like above

Joi.object({}).meta({ description: 'A description of FooBar' });

Type naming

To override the type a Joi model should be interpreted as, use the Joi.meta() option like above. This is especially useful when utilizing the extend and coerce features of Joi schema definition

Joi.object({}).meta({ swaggerType: string });

Document responses

There are 2 and a half different ways of documenting responses of routes:

The hapi way:

{
  options: {
    response: {
      schema: Joi.object({
        bar: Joi.string().description('test').required()
      }).description('test'),
      status: {
        500: Joi.object({
          bar: Joi.string().description('test').required()
        })
      }
    }
  }
}

The plugin way without schemas:

{
  options: {
    plugins: {
      'hapi-swaggered': {
        responses: {
          default: {description: 'Bad Request'},
          500: {description: 'Internal Server Error'}
        }
      }
    },
    response: {
      schema: Joi.object({
        bar: Joi.string().required()
      }).description('test')
    }
  }
}

The plugin way with schemas:

{
  options: {
    plugins: {
      'hapi-swaggered': {
        responses: {
          default: {
            description: 'Bad Request', schema: Joi.object({
              bar: Joi.string().description('test').required()
            })
          },
          500: {description: 'Internal Server Error'}
        }
      }
    }
  }
}

Specify an operationId for a route:

{
  options: {
    plugins: {
      'hapi-swaggered': {
        operationId: 'testRoute'
      }
    }
  }
}

Specify an security options to a route / operation:

{
  options: {
    plugins: {
      'hapi-swaggered': {
        security: {}
      }
    }
  }
}

Tag filtering

Routes can be filtered for tags through the tags query parameter beside the requiredTags property which is always required to be present.

For example:

Known issues

No response types

The routes response schemas which hapi-swaggered is parsing will be dropped by hapi whenever the response validation is disabled. In this case hapi-swaggered will not be able to show any response types. A very low sampling rate is sufficient to keep the repsonse types.