npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typescript-openapi-router

v3.1.5

Published

Multi purpose yet simple nodejs router with OpenAPI 3 compatibility for REST APIs

Downloads

176

Readme

openapi-router

A (very opinionated, no dependency) NodeJS Typescript router that implements the OpenAPI 3 spec implemented with the serverless framework in mind.

Early stage development, not to be used in production apps.

See app implementation example here

Router components

  • Router
  • Validator
  • Class and method decorators for OpenAPI 3
  • Documentation generator

Router

Router is provided as a singleton and can be obtained by calling getRouter(). The router exposes two methods handleEvent and getApiDoc.

The handleEvent method receives a Request parameter (see bellow) that contains all the information needed to process the request.

export class Request<RequestBody = any> {
  headers?: { [key: string]: string };
  path: string;
  method: HttpMethod;
  body?: RequestBody;
  pathParams?: IPathParams | null;
  queryParams?: IQueryParams | null;
  ...
}

The handleEvent method will search for the correct handler to process the request.

Middleware

The router also supports optional middleware that can execute functions before and after the original handler (you can add a top level logging of the request and response for all handlers for example or alter the request or the response)

The @Route supports the middleware property which in turn has the before and after properties (which are arrays of BeforeMiddlewareHandler and AfterMiddlewareHandler)

The @ApiRouter supports global middleware. The global before functions will be executed before each handler's middleware functions. The global after functions will be executed after each handler's middleware functions. It's good for situations where you want to log/persist all the requests and all the responses.

Example


export const beforeAuth: BeforeMiddlewareHandler = async (request:Request<AuthRequest>): Promise<Request> => {
  if (request.body) {
    request.body.email = `before-${request.body.email}`;
  }
  return request;
};

export const afterAuth: AfterMiddlewareRequestHandler = async (response: Response<AuthResponse>): Promise<Response> => {
  if (response.body) {
    const body = response.getBody();
    if (body) {
      body.message = body.message + " after";
      response.setBody(body);
    }
  }
  return response;
};


@Route({
    ...
    middleware: {
      before: [
        beforeAuth
      ],
      after: [
        afterAuth
      ]
    }
   ...
  })

See here a more detailed implementation

Validator

The validator is used to validate the input and output. It is done automatically and relies on the OpenAPI 3 specs (see implementation, tests and example project). The validator returns common sense error messages like AuthRequest.email is required, UserDetails.lastName should be of type string etc

Decorators

There are two decorators defined DocMetadata which defines the documentation info and global settings and Route which registers a method with the router and defines the behaviour and documentation for a route.

DocMetadata example

@DocMetadata({
  version: "1.0.0",
  title: "A test app",
  description: "Exactly as the name suggests",
  contact: {
    name: "Vali Draganescu",
    email: "[email protected]",
    url: "https://technoloid.com"
  },
  termsOfService: "https://technoloid.com/terms",
  license: {
    name: "DWETFYW | Do what ever the fuck you want",
    url: "https://technoloid.com/license"
  },
  securitySchemes: {
    ApiKeyAuth: {
      type: "apiKey",
      in: "header",
      name: "X-API-Key"
    },
    BearerAuth: {
      type: "http",
      scheme: "bearer"
    }
  },
  security: [
    {
      ApiKeyAuth: []
    },
    {
      BearerAuth: []
    }
  ],
  servers: [{
    url: "localhost:8080",
    description: "localhost"
  }, {
    url: "https://dev-api.test.com",
    description: "Development"
  }, {
    url: "https://api.test.com",
    description: "Production"
  }],
  globalResponses: [
    {
      statusCode: 500,
      description: "Internal server error",
      body: ErrorResponse
    }
  ]
})

Route example

@Route({
    description: "simple method, just says hello to the user",
    summary: "This is the summary",
    method: HttpMethod.GET,
    path: "/hello",
    responses: [{
      statusCode: 200,
      description: "hello response",
      body: HelloResponse
    }]
  })

Documentation generator

The router also defines the method getApiDoc which returns an OpenAPI 3 standard json documentation based on the DocMetadata and Routes defined in the API implementation. The globalResponses from the DocMetadata can be used to define global responses for all routes. Think like 404, 401, 500 etc status messages. This responses will be added to any route that does not already define them.

Default headers for all API responses

{
    "Content-Type": "application/json",
    "Cache-Control": "private, max-age=0, no-cache, no-store, must-revalidate'",
    "Expires": "-1",
    "Pragma": "no-cache",
    "Access-Control-Expose-Headers": "X-Api-Version",
    "Access-Control-Allow-Origin" : "*",
    "Access-Control-Allow-Credentials": "true"
}

Can be overridden using one of the following methods

  addHeader = (key: string, value: string) => {
    this.headers[key] = value;
  };

  addHeaders = (headers: { [key: string]: string }) => {
    for (const [key, value] of Object.entries(headers)) {
      this.addHeader(key, value);
    }
  };

  setHeaders = (headers: { [key: string]: string }) => {
    this.headers = headers;
  };

Licence

License

Distributed under European Union Public License, version 1.2 (EUPL-1.2)