0.3.1 • Published 5 months ago

@oselvar/openapi-validator v0.3.1

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

This is a small library that validates HTTP requests and responses against an OpenAPI 3.0 specification.

It is designed to work with any web servers/framework that uses the Fetch API such as:

It also provides adapters for non-Fetch based web servers/frameworks such as:

The library is built on top of Zod and zod-to-openapi.

Installation

npm install --save @oselvar/openapi-validator

Define an OpenAPI route

import { RouteConfig } from '@asteasolutions/zod-to-openapi';
import { z } from 'zod';

import {
  Response404,
  Response415,
  Response422,
  Response500,
} from '@oselvar/openapi-validator';

// Define Zod schemas for the request parameters, query and body

const ThingParamsSchema = z.object({
  thingId: z.string().regex(/[\d]+/),
});

const ThingQuerySchema = z.object({
  thingId: z.string().regex(/[\d]+/).optional(),
});

const ThingBodySchema = z.object({
  name: z.string().regex(/[a-z]+/),
  description: z.string().regex(/[a-z]+/),
});

// Define an OpenAPI route using https://github.com/asteasolutions/zod-to-openapi

const routeConfig: RouteConfig = {
  method: 'post',
  path: '/things/{thingId}',
  request: {
    params: ThingParamsSchema,
    query: ThingQuerySchema,
    body: {
      content: {
        'application/json': {
          schema: ThingBodySchema,
        },
      },
    },
  },
  responses: {
    200: {
      description: 'Create a thing',
      content: {
        'application/json': {
          schema: ThingBodySchema,
        },
      },
    },
    404: Response404,
    415: Response415,
    422: Response422,
    500: Response500,
  },
};

Create a validator

The Validator class uses the schemas in the routeConfig object to validate requests and responses.

import { Validator } from '@oselvar/openapi-validator';

const validator = new Validator(routeConfig);

Validate requests and responses

Your web server will provide a request object and a params object.

(If your web server does not use the Fetch API, see the Adapters section below.)

const request: Request = ...;
const params: Record<string, string | undefined> = ...;

const params = validator.params<z.infer<typeof ThingParamsSchema>>(params);
const body = await validator.body<z.infer<typeof ThingBodySchema>>(request);
const response = validator.validate(Response.json(body));

Error handling

The methods on the Validator object will throw a ValidationError if the request or response is invalid. You must handle this error and return an appropriate HTTP response to the client.

We recommend doing this in a middleware function. Please refer to your web server's documentation for more information.

Here is an example:

import { unwrapError } from '@oselvar/openapi-validator';

try {
  // Run the handler
} catch (error) {
  const { message, response } = unwrapError(error);
  console.error(response.status, message);
  return response;
}

Adapters

If you are using a framework that does not use the Fetch API Request and Response objects such as AWS Lambda, Express or Fastify, use the FetchRoute type to define your handler function:

import { FetchRoute, Validator } from '@oselvar/openapi-validator';
import { RouteConfig } from '@asteasolutions/zod-to-openapi';
import { z } from 'zod';

const routeConfig: RouteConfig = { ... };
const validator = new Validator(routeConfig);

const fetchRoute: FetchRoute = async (context) => {
  const params = validator.params<z.infer<typeof ThingParamsSchema>>(context.params);
  const body = await validator.body<z.infer<typeof ThingBodySchema>>(context.request);
  return validator.validate(Response.json(body));
};

Note that the support for multiple HTTP servers can also simplify your developer experience. You can write your handler function once and then register it with multiple HTTP servers.

For example, you can register your handler functions with Express or Fastify during development and then register them with AWS Lambda during production.

The next step is to convert the FetchRoute to a function that can be registered with your HTTP server.

AWS Lambda

import { FetchOpenAPIHandler } from '@oselvar/openapi-validator';
import { toProxyHandler } from '@oselvar/openapi-validator/aws-lambda';

export const handler = toProxyHandler(fetchRoute);

Express

Coming soon.

Fastify

Coming soon.

0.3.1

5 months ago

0.3.0

5 months ago

0.2.1

5 months ago

0.2.0

5 months ago

0.1.0

5 months ago