Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-openapi-decorator

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-openapi-decorator

An opiniated library using decorators in order to define openAPI documentation for an endpoint.

  • 0.0.6
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
7
increased by600%
Maintainers
1
Weekly downloads
 
Created
Source

express-openapi-decorator

An opiniated library using decorators in order to define openAPI documentation for an expressJs endpoint.

@doc({
    summary: 'This endpoint will display Hello world.',
})
class HelloWorld extends Endpoint {
    @queryParam({ description: 'The name of person to great.', example: 'Alex' })
    name?: string;

    @errorResponse()
    errorForbidden = new Error(`This name is forbidden.`);

    handler() {
        if (this.name === 'voldemort') {
            throw this.errorForbidden;
        }
        this.res.send(`Hello ${this.name || 'world'}`);
    }
}

This library is not a validator. To validate incoming request use express-openapi-validator

How to use

Install peer dependency:

npm install express

Create a class, extending the abstract class Endpoint, for each endpoints.

@doc({
    summary: 'This endpoint will display Hello world.',
})
class HelloWorld extends Endpoint {
    handler() {
        this.res.send('Hello world');
    }
}

The OpenApi documentation is part of the endpoint instance:

console.log(new HelloWorld().doc);

Add the endpoint to the Router:

import { router } from 'express-openapi-decorator';

const router = Router();
router.get('/api/hello', new HelloWorld());

Create api doc:

const doc: OpenAPIV3.Document = {
    openapi: '3.0.1',
    info: {
        description: 'This API serve an example.',
        version: '1.0.0',
        title: 'Hello world',
    },
    paths: router.doc,
};

Expose router and doc with express:

const port = 3000;
const app = express();
app.get('/api-docs', (_req, res) => res.json(doc));
app.use(router);
app.listen(port, () => {
    logger.info(`Ready to accept connections on port: ${port}`);
});

To visualize the OpenApi documentation use swagger-ui-express: app.use('/ui', swaggerUi.serve, swaggerUi.setup(apiDoc));

Router

const router = Router(); is an extension of express Router, working the same way, but instead to pass request handler to the route, endpoints should be passed.

router.get(path: string, ...endpoints: Endpoint[]) will add the endpoint instances to the given path for the get method (this work for any method). It allow to merge multiple endpoints definition to one, this can be useful for example to create a security middleware:

@doc({
    security: [{ basicAuth: [] }],
})
class SecureEndpoint extends Endpoint {
    handler() {
        if (this.req.headers['authorization'] !== `Basic ${btoa('user:password')}`) {
            throw new Error('Invalid credential');
        }
        next();
    }
}

@doc({
    summary: 'This endpoint will display Hello world.',
})
class HelloWorld extends Endpoint {
    handler() {
        this.res.send('Hello world');
    }
}

router.get('/api/hello', new SecureEndpoint(), new HelloWorld());

router can then be used like a normal express router:

app.use(router);

It is possible to access the endpoints instances with router.endpointInstances.

router.doc return the OpenApi doc for each endpoints added to the router according there path and method.

const app = express();
const doc: OpenAPIV3.Document = {
    openapi: '3.0.1',
    info: {
        description: 'This API serve an example.',
        version: '1.0.0',
        title: 'Hello world',
    },
    paths: router.doc,
};
app.get('/api-docs', (_req, res) => res.json(doc));

Decorators

To define the characteristic of the endpoint, we use decorators.

@doc

The @doc decorator get an OpenAPIV3.OperationObject as first parameter, meaning that it is possible to define the whole endpoint documentation here. However, this definition might get partly overwritten by the following decorators.

@doc({
    summary: 'This endpoint will display Hello world.',
})
class HelloWorld extends Endpoint {}

@pathParam

The @pathParam decorator get an OpenAPIV3.ParameterBaseObject as first parameter, to define the documentation of path parameter. When express will call the handler, the value of the parameter will be automatcally be populated to the endpoint object.

class HelloWorld extends Endpoint {
    @pathParam({ description: 'The name of person to great.', required: true, example: 'Alex' })
    name!: string;

    handler() {
        this.res.send(`Hello ${this.name}`);
    }
}

@queryParam

The @queryParam decorator get an OpenAPIV3.ParameterBaseObject as first parameter, to define the documentation of a query parameter. When express will call the handler, the value of the parameter will be automatcally be populated to the endpoint object.

class HelloWorld extends Endpoint {
    @queryParam({ description: 'The name of person to great.', required: true, example: 'Alex' })
    name!: string;

    handler() {
        this.res.send(`Hello ${this.name}`);
    }
}

@bodyProp

The @bodyProp decorator get an OpenAPIV3.BodySchema as first parameter, to define the documentation of a property from the body sent in the request. When express will call the handler, the value of the property will be automatcally be populated to the endpoint object.

class HelloWorld extends Endpoint {
    @bodyProp({ description: 'The name of person to great.', required: true, example: 'Alex' })
    name!: string;

    handler() {
        this.res.send(`Hello ${this.name}`);
    }
}

@errorResponse

The @errorResponse decorator get an optional OpenAPIV3.ResponsesObject as first parameter. The value of error property must be of type Error, where the message will be automatically used as description in the OpenApi documentation.

class HelloWorld extends Endpoint {
    @errorResponse()
    errorConflict = new Error(`This endpoint is in conflict.`);

    async handler() {
        throw this.errorConflict;
    }
}

Or with status code

class Conflict extends Error {
    statusCode = 409;
}

class HelloWorld extends Endpoint {
    @errorResponse()
    errorConflict = new Conflict(`This endpoint is in conflict.`);

    async handler() {
        throw this.errorConflict;
    }
}

or using http-errors library

import { Conflict } from 'http-errors';

class HelloWorld extends Endpoint {
    @errorResponse()
    errorConflict = new Conflict(`This endpoint is in conflict.`);

    async handler() {
        throw this.errorConflict;
    }
}

FAQs

Package last updated on 15 Dec 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc