NestJS Integration
Tspec supports generating OpenAPI specifications directly from NestJS controllers. This allows you to automatically generate API documentation without manually defining type specifications.
Prerequisites
Before using NestJS integration, make sure you have:
- A NestJS project with TypeScript
- Controllers using NestJS decorators (
@Controller,@Get,@Post, etc.)
Installation
Install tspec in your NestJS project:
yarn add tspecnpm install tspecpnpm add tspecBasic Usage
Example Controller
Assume you have the following NestJS controller:
import { Controller, Get, Post, Put, Delete, Param, Query, Body } from '@nestjs/common';
interface Book {
id: number;
title: string;
author: string;
}
interface CreateBookDto {
title: string;
author: string;
}
interface BookListQuery {
page?: number;
limit?: number;
}
/**
* Books API Controller
*/
@Controller('books')
export class BooksController {
/**
* Get all books with pagination
* @summary List all books
*/
@Get()
findAll(@Query() query: BookListQuery): Promise<Book[]> {
// implementation
}
/**
* Get a single book by ID
* @summary Get book by ID
*/
@Get(':id')
findOne(@Param('id') id: string): Promise<Book> {
// implementation
}
/**
* Create a new book
* @summary Create book
*/
@Post()
create(@Body() createBookDto: CreateBookDto): Promise<Book> {
// implementation
}
/**
* Update an existing book
* @summary Update book
*/
@Put(':id')
update(
@Param('id') id: string,
@Body() updateBookDto: CreateBookDto,
): Promise<Book> {
// implementation
}
/**
* Delete a book
* @summary Delete book
*/
@Delete(':id')
remove(@Param('id') id: string): Promise<void> {
// implementation
}
}Generate OpenAPI Spec
Generate OpenAPI specification directly from your NestJS controllers using the --nestjs flag:
yarn tspec generate --nestjsnpx tspec generate --nestjspnpm tspec generate --nestjsGenerated OpenAPI Spec
openapi: 3.0.3
info:
title: NestJS API
version: 1.0.0
paths:
/books:
get:
operationId: BooksController_findAll
summary: List all books
description: Get all books with pagination
tags:
- Books
parameters:
- name: page
in: query
required: false
schema:
type: number
- name: limit
in: query
required: false
schema:
type: number
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Book'
post:
operationId: BooksController_create
summary: Create book
tags:
- Books
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateBookDto'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
/books/{id}:
get:
operationId: BooksController_findOne
summary: Get book by ID
tags:
- Books
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
put:
operationId: BooksController_update
summary: Update book
tags:
- Books
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateBookDto'
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
delete:
operationId: BooksController_remove
summary: Delete book
tags:
- Books
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
'204':
description: No ContentCLI Options
When using --nestjs flag, the following options are available:
| Option | Default | Description |
|---|---|---|
--nestjs | false | Enable NestJS controller parsing |
--tsconfigPath | tsconfig.json | Path to TypeScript config file |
--specPathGlobs | src/**/*.controller.ts | Glob patterns to find controller files |
--outputPath | openapi.json | Output path for generated OpenAPI spec |
--openapiTitle | Tspec API | API title in OpenAPI info |
--openapiVersion | 0.0.1 | API version in OpenAPI info |
--openapiDescription | `` | API description in OpenAPI info |
Example with all options
npx tspec generate --nestjs \
--tsconfigPath tsconfig.json \
--specPathGlobs 'src/**/*.controller.ts' \
--outputPath docs/openapi.json \
--openapiTitle 'My NestJS API' \
--openapiVersion '2.0.0' \
--openapiDescription 'API documentation for my NestJS application'Supported Decorators
Tspec parses the following NestJS decorators:
Controller Decorators
@Controller(path?)- Defines the base path for all routes in the controller
HTTP Method Decorators
@Get(path?)@Post(path?)@Put(path?)@Patch(path?)@Delete(path?)@Options(path?)@Head(path?)
Parameter Decorators
@Param(name?)- Path parameters@Query()- Query parameters@Body()- Request body@Headers()- Header parameters
Swagger Decorators
@ApiTags(...tags)- Adds tags to all operations in the controller@ApiResponse({ status, description?, type? })- Defines response status codes and types
JSDoc Support
Tspec extracts documentation from JSDoc comments:
/**
* This becomes the operation description
* @summary This becomes the operation summary
* @tag CustomTag
*/
@Get()
findAll(): Promise<Book[]> {
// ...
}Limitations
The current NestJS integration has some limitations:
- Type inference: Complex generic types may not be fully resolved
- Custom decorators: Only standard NestJS decorators are supported
- Validation decorators:
class-validatordecorators are not parsed - Interceptors/Guards: These are not reflected in the generated spec
TIP
For more advanced use cases, consider using the standard Tspec approach with Tspec.DefineApiSpec alongside your NestJS controllers.
Programmatic API
You can generate OpenAPI specs programmatically using the generateTspec function with nestjs: true:
import { generateTspec } from 'tspec';
const spec = await generateTspec({
tsconfigPath: './tsconfig.json',
specPathGlobs: ['src/**/*.controller.ts'],
nestjs: true,
openapi: {
title: 'My API',
version: '1.0.0',
description: 'My NestJS API documentation',
},
});
// Use the spec object directly or write to file
console.log(JSON.stringify(spec, null, 2));Options
| Option | Type | Default | Description |
|---|---|---|---|
tsconfigPath | string | ./tsconfig.json | Path to TypeScript config file |
specPathGlobs | string[] | ['src/**/*.controller.ts'] | Glob patterns to find controller files |
nestjs | boolean | false | Enable NestJS controller parsing mode |
outputPath | string | - | Output path for generated OpenAPI spec |
openapi.title | string | Tspec API | API title |
openapi.version | string | 0.0.1 | API version |
openapi.description | string | - | API description |
openapi.securityDefinitions | object | - | Security schemes |
openapi.servers | array | - | Server URLs |
Using @ApiResponse
Tspec supports the @ApiResponse decorator from @nestjs/swagger to define multiple response types:
import { Controller, Get, Param } from '@nestjs/common';
import { ApiResponse } from '@nestjs/swagger';
class Book {
id: number;
title: string;
author: string;
}
class ErrorResponse {
message: string;
statusCode: number;
}
@Controller('books')
export class BooksController {
@Get(':id')
@ApiResponse({ status: 200, description: 'Book found', type: Book })
@ApiResponse({ status: 404, description: 'Book not found', type: ErrorResponse })
@ApiResponse({ status: 500, description: 'Internal server error' })
findOne(@Param('id') id: string): Promise<Book> {
// implementation
}
}This generates the following responses in OpenAPI:
responses:
'200':
description: Book found
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
'404':
description: Book not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server errorTIP
When @ApiResponse decorators are present, they override the default response generation based on return type.
Using @ApiTags
Tspec supports the @ApiTags decorator from @nestjs/swagger to organize your API operations:
import { Controller, Get } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
@ApiTags('Users', 'Admin')
@Controller('users')
export class UsersController {
@Get()
findAll(): Promise<User[]> {
// This operation will have tags: ['Users', 'Admin']
}
}You can also use enum values or constants:
enum ApiTag {
USERS = 'users',
ADMIN = 'admin',
}
@ApiTags(ApiTag.USERS, ApiTag.ADMIN)
@Controller('users')
export class UsersController {
// ...
}Combining with Standard Tspec
You can use both approaches in the same project:
- Use
--nestjsflag for quick documentation of existing controllers - Use
Tspec.DefineApiSpecfor APIs that need more detailed specifications
# Generate from NestJS controllers
npx tspec generate --nestjs --outputPath openapi-nest.json
# Generate from Tspec definitions
npx tspec generate --outputPath openapi-tspec.json