Skip to content

qteab/nest-border-patrol

Repository files navigation

Nest Border Patrol

A package for validating NestJS HTTP controller endpoints using zod. Integrates with NestJS swagger.

Getting started

Install the package:

npm i @qte/nest-border-patrol
yarn add @qte/nest-border-patrol
pnpm add @qte/nest-border-patrol

You also will need the following dependencies if you haven't installed them already

  • @nestjs/common
  • @nestjs/swagger
  • rxjs
  • zod

Usage

Create a new HttpBorder(options) instance. Options are the following

  • requestBody (optional) - Any Zod schema
  • parameters (optional)
    • path (optional) - A string record of Zod schemas where the key is the name of your URL parameters
    • query (optional) - A string record of Zod schemas
  • responses - A record with keys of HttpStatus and values of any zod schema

To make use of the newly created HttpBorder you decorate your controller endpoint with the @UseHttpBorder() decorator. This will in turn validate the incoming request and outgoing responses with the supplied schemas in the HttpBorder constructor.

The @UseHttpBorder() decorator will also decorate your controller method with matching @nestjs/swagger decorators for generating OpenAPI schemas.

Example

import { Body, Controller, HttpStatus, Param, Post, Query } from '@nestjs/common';
import { z } from 'zod';
import {
  HttpBorder,
  InferFromHttpBorder,
  UseHttpBorder
} from '@qte/nest-border-patrol';

// Create a border
const border = new HttpBorder({
  requestBody: z.object({
    name: z.string(),
  }),
  parameters: {
    path:  {
      someParam: z.string(),
    },
    query: {
      someQueryParam: z.string().optional(),
    },
  }
  responses: {
    [HttpStatus.CREATED]: z.object({
      publicData: z.string(),
    }),
  }
});

@Controller()
export class SampleController {
  @Post('/:someParam')
  @UseHttpBorder(border)
  public async post(
    // Will be typed as:
    //  { name: string }
    @Body() body: InferFromHttpBorder<typeof border, 'requestBody'>,
    // Will be typed as:
    // { someQueryParam: string | undefined; }
    @Query() query: InferFromHttpBorder<typeof border, 'queryParameters'>,
    // Will be typed as:
    // { someParam: string; }
    @Param() params: InferFromHttpBorder<typeof border, 'pathParameters'>
  ): // Will be typed as:
  // HttpBorderResponse<HttpStatus.CREATED, { publicData: string; }>
  Promise<InferFromHttpBorder<typeof border, 'response'>> {
    return border.createResponse(HttpStatus.CREATED, {
      publicData: 'Hello world',
      // This property will stripped from the response as
      // it is not defined in the response schema.
      sensitiveData: 'password',
    });
  }
}

Versioning

Until the package reaches 1.0.0 all updates may be breaking.

Potential roadmap

  • Validating headers incoming and outgoing
  • OpenAPI example values
  • Test typings using // @ts-expect-error
  • Validate query params as an object (OpenAPI issues)
  • Validate unnamed query params

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published