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 🙏

© 2026 – Pkg Stats / Ryan Hefner

nest-openapi

v1.0.12

Published

Auto generate openapi spec from nest.js codebase with single command

Readme

nest-openapi

💡 If you use Nest.js with class-validator, this package is for you.

Motivation

😇 Life is too short to write API docs manually.

I was tried of using bunch of nest.js swagger decorators for auto generating openapi spec. Code looked ugly. Too much extra code just to get the basic openapi structure.

I looked for a solution that could generate the spec just by looking into the nest.js codebase. I couldn't find any so I built one.

What it does

{
  "openapi": "3.1.0",
  "info": {
    "title": "User API",
    "version": "1.0.0",
    "description": "An example API to create a user, optionally with a referrer ID."
  },
  "servers": [{ "url": "https://api.example.com/v1" }],
  "paths": {
    "/users/{referrerId}": {
      "post": {
        "summary": "Create a new user",
        "operationId": "createUser",
        "tags": ["Users"],
        "parameters": [{ "$ref": "#/components/parameters/ReferrerId" }],
        "requestBody": {
          "$ref": "#/components/requestBodies/CreateUserRequest"
        },
        "responses": {
          "201": { "$ref": "#/components/responses/UserCreated" },
          "400": { "$ref": "#/components/responses/BadRequest" }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "ReferrerId": {
        "name": "referrerId",
        "in": "path",
        "required": true,
        "description": "The ID of the user who referred the new user",
        "schema": { "type": "string", "example": "ref123" }
      }
    },
    "schemas": {
      "User": {
        "type": "object",
        "properties": {
          "id": { "type": "string", "example": "abc123" },
          "name": { "type": "string", "example": "John Doe" },
          "email": {
            "type": "string",
            "format": "email",
            "example": "[email protected]"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2025-01-01T12:00:00Z"
          },
          "referrerId": {
            "type": "string",
            "nullable": true,
            "example": "ref123"
          }
        },
        "required": ["id", "name", "email", "createdAt"]
      },
      "CreateUserInput": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "example": "John Doe" },
          "email": {
            "type": "string",
            "format": "email",
            "example": "[email protected]"
          },
          "password": {
            "type": "string",
            "format": "password",
            "example": "P@ssw0rd!"
          }
        },
        "required": ["name", "email", "password"]
      },
      "Error": {
        "type": "object",
        "properties": {
          "message": { "type": "string", "example": "Invalid request payload" }
        }
      }
    },
    "requestBodies": {
      "CreateUserRequest": {
        "description": "User creation request payload",
        "required": true,
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/CreateUserInput" }
          }
        }
      }
    },
    "responses": {
      "UserCreated": {
        "description": "User successfully created",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/User" }
          }
        }
      },
      "BadRequest": {
        "description": "Invalid request payload",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Error" }
          }
        }
      }
    }
  }
}

How to use

Generate openapi spec with single command

> pnpm add nest-openapi -g
> nest-openapi

Live preview for development

nest-openapi -p 8000

CLI options

| option | default value | | ------------ | ------------- | | -o, --output | openapi.json | | -p, --port | 8080 |

Basic patterns to follow.

Just need to maintain the codebase and follow some basic patterns. The package will handle the rest.

  1. Class name in whole project must be unique. Better to use prefix and suffix with class names.
  2. While using nest.js decorators i.e. @Param, @Body, @Query, etc. always use class as type annotation and add validations using class-validator.
  3. Define return type annotation of the endpoint with separate class. It can be a regular class, I'm just used to writing code like below.

Here is the code example

export class ProductIdDto {
  @IsMongoId()
  productId: string
}

export class ProductUpdateDto {
  @IsNotEmpty()
  @IsString()
  name: string

  @IsNotEmpty()
  @IsString()
  description: string
}

export class ProductSerializer {
  @Expose() id: string
  @Expose() name: string
  @Expose() description: string
  @Expose() @Type(() => Date) createdAt: string
  @Expose() @Type(() => Date) updatedAt: string
}

@Controller('products')
export class ProductController {
  @Patch(':productId')
  async updateProduct(
    @Body() productUpdateDto: ProductUpdateDto,
    @Param() { productId }: ProductIdDto,
  ): Promise<ProductSerializer> {
    // logic here
    console.log({ productId })
    return plainToInstance(ProductSerializer, productUpdateDto, {
      strategy: 'excludeAll',
    })
  }
}

How it works

  • To navigate through typescript AST it uses ts-morph. It looks for classes with @Controller decorator and loops over the methods.
  • To generate example for the schemas it uses @faker-js/faker with json-schema-faker
  • To turn dto into schema it uses class-validator-jsonschema, since it supports class-validator validation decorators.
  • To turn response class to schema it uses ts-json-schema-generator.
  • It uses controller class name and method name for operation id {controllerClassName}-{methodName}

customization

With config file

Create nest-openapi.config.ts file in the project root directory.

import { Config } from 'nest-openapi'

const config: Config = {
  extends: {
    servers: [
      { url: 'https://dev.example.com', description: 'Development' },
      { url: 'https://example.com', description: 'Production' },
    ],
    components: {
      /** responses below will be included in every operations */
      responses: {
        '401': {
          description: 'Unauthorized',
        },
        '402': {
          description: 'Payment required',
        },
        '500': {
          description: 'Server error',
          content: {
            'application/json': {
              schema: {
                type: 'object',
                properties: {
                  error: {
                    type: 'string',
                    example: 'Server error',
                  },
                  message: {
                    type: 'string',
                    example: 'Internal server error',
                  },
                },
              },
            },
          },
        },
      },
    },
  },

  /** glob pattern for typescript AST */
  glob: ['src/**/*.ts', '!src/**/*.spec.ts', '!src/**/*.e2e-spec.ts'],
}

export default config

With comments

  1. use js-doc @tag and @description to have custom tag name and description.

    /**
     * @tag Users
     * @description IT contains APIs to work with users.
     */
    @Controller()
    export class UserController {}
  2. use @summary, @description, @deprecated in endpoints.

      /**
       * @summary Method name
       * @description Use this endpoint do the the task.
       * @deprecated This endpoint is deprecated, use [this](#tag/className-methodName) endpoint.
       */
      @Patch()
      async methodName() {}
  3. use @description in the properties of the class.

    class Dto {
      /** @description This is a description. */
      property: string
    }