Skip to content
Download

OpenAPI (Swagger)

Bunstone provides built-in support for OpenAPI (Swagger) documentation using decorators, similar to NestJS.

Installation

OpenAPI support is built-in, but you need to enable it in your AppStartup.

Configuration

Enable Swagger in your AppStartup.create options:

typescript
await AppStartup.create(AppModule, {
  swagger: {
    path: "/docs", // default is /swagger
    documentation: {
      info: {
        title: "My API",
        version: "1.0.0",
        description: "API Documentation",
      },
    },
  },
}).listen(3000);

Basic Auth Protection

You can optionally protect the Swagger documentation page with HTTP Basic Authentication by providing auth credentials:

typescript
await AppStartup.create(AppModule, {
  swagger: {
    path: "/docs",
    auth: {
      username: "admin",
      password: "secret",
    },
    documentation: {
      info: {
        title: "My API",
        version: "1.0.0",
      },
    },
  },
}).listen(3000);

When auth is set, any request to the documentation path (and its sub-paths such as /docs/json) will require a valid Authorization: Basic <base64(username:password)> header. Unauthenticated requests receive a 401 Unauthorized response with a WWW-Authenticate challenge, which causes browsers to display a native login dialog. For security, you should only expose this endpoint over HTTPS (or behind a reverse proxy that terminates HTTPS), as Basic Auth credentials are otherwise sent in clear text and can be intercepted.

Decorators

@ApiTags()

Adds tags to a controller or a specific method.

typescript
@ApiTags("Users")
@Controller("users")
export class UserController {
  @ApiTags("Profile")
  @Get("profile")
  getProfile() {}
}

@ApiOperation()

Defines the summary and description for an endpoint.

typescript
@ApiOperation({ summary: 'Create a user', description: 'This endpoint creates a new user in the database' })
@Post()
create() {}

@ApiResponse()

Defines the possible responses for an endpoint.

typescript
@ApiResponse({ status: 200, description: 'User found' })
@ApiResponse({ status: 404, description: 'User not found' })
@Get(':id')
findOne() {}

@ApiHeader() / @ApiHeaders()

Defines custom headers for an endpoint or controller.

typescript
@ApiHeader({ name: "X-Custom-Header", description: "A custom header" })
@Controller("users")
export class UserController {
  @ApiHeaders([
    { name: "X-Token", description: "Auth token", required: true },
    { name: "X-Version", description: "API Version" },
  ])
  @Get()
  findAll() {}
}

DTOs and Schemas

Bunstone uses Zod for validation. When you use @Body(Schema), @Query(Schema), or @Param(Schema), the schema is automatically registered in the OpenAPI documentation.

typescript
const CreateUserSchema = z.object({
  name: z.string(),
  email: z.string().email()
});

@Post()
@ApiOperation({ summary: 'Create user' })
create(@Body(CreateUserSchema) body: any) {
  return body;
}

Practical Example

Explore a complete OpenAPI configuration and usage:

ts
import {
  Module,
  Controller,
  Get,
  Post,
  Body,
  AppStartup,
  ApiTags,
  ApiOperation,
  ApiResponse,
} from "../../index";
import { z } from "zod";

const UserSchema = z.object({
  id: z.string(),
  name: z.string(),
});

@ApiTags("Users")
@Controller("users")
class UserController {
  @Get()
  @ApiOperation({ summary: "List all users" })
  @ApiResponse({ status: 200, description: "Return all users" })
  getUsers() {
    return [];
  }

  @Post()
  @ApiOperation({ summary: "Create a user" })
  @ApiResponse({ status: 201, description: "User created" })
  createUser(@Body(UserSchema) body: z.infer<typeof UserSchema>) {
    return body;
  }
}

@Module({
  controllers: [UserController],
})
class AppModule {}

const app = await AppStartup.create(AppModule, {
  swagger: {
    path: "/docs",
    title: "Bunstone API",
    version: "1.0.0",
  },
});

app.listen(3000, () => {
  console.log("OpenAPI (Swagger) is available at http://localhost:3000/docs");
});

See it on GitHub

Released under the MIT License.