Skip to content

@kubb/plugin-oas

Parse and validate your OpenAPI schema with this core plugin.

Installation

shell
bun add -d @kubb/plugin-oas
shell
pnpm add -D @kubb/plugin-oas
shell
npm install --save-dev @kubb/plugin-oas
shell
yarn add -D @kubb/plugin-oas

Options

output

Specify the export location for the files and define the behavior of the output.

output.path

Path to the output folder or file that contains the generated code.

TIP

if output.path is a file, group cannot be used.

Type:string
Required:true
Default:'schemas'

output.barrelType

Specify what to export and optionally disable barrel file generation.

TIP

Using propagate will prevent a plugin from creating a barrel file, but it will still propagate, allowing output.barrelType to export the specific function or type.

Type:'all' | 'named' | 'propagate' | false
Required:false
Default:'named'
typescript
export * from "./gen/petService.ts"
typescript
export { PetService } from "./gen/petService.ts"
typescript
typescript

output.banner

Add a banner comment at the top of every generated file.

Type:string | (oas: Oas) => string
Required:false

Add a footer text at the end of every file.

Type:string | (oas: Oas) => string
Required:false

output.override

Whether Kubb overrides existing external files that can be generated if they already exist.

Type:boolean
Required:false
Default:false

group

Grouping combines files in a folder based on a specific type.

For example, with this configuration:

kubb.config.ts
typescript
group: {
  type: 'tag',
  name({ group }){
    return `${group}Controller`
  }
}

This generates the following structure:

.
├── src/
│   └── petController/
│   │   ├── addPet.ts
│   │   └── getPet.ts
│   └── storeController/
│       ├── createStore.ts
│       └── getStoreById.ts
├── petStore.yaml
├── kubb.config.ts
└── package.json

group.type

Specify the property to group files by. Required when group is defined.

Type:'tag'
Required:true*

NOTE

Required: true* means this is required only when the group option is used. The group option itself is optional.

  • 'tag': Uses the first tag from operation.getTags().at(0)?.name

group.name

Return the name of a group based on the group name, this will be used for the file and name generation.

Type:(context: GroupContext) => string
Required:false
Default:(ctx) => '${ctx.group}Controller'

validate

Validate your input based on @readme/openapi-parser.

Type:boolean
Required:false
Default:true

serverIndex

Which server to use from the array of servers.url[serverIndex]

TIP

Defining the server here will make it possible to use that endpoint as baseURL in other plugins.

Type:number
Required:false
  • 0 will return http://petstore.swagger.io/api
  • 1 will return http://localhost:3000
yaml
openapi: 3.0.3
info:
  title: Swagger Example
  description:
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.0
servers:
- url: http://petstore.swagger.io/api
- url: http://localhost:3000
typescript
import { pluginOas } from '@kubb/plugin-oas'

const plugin = pluginOas({ serverIndex: 0 })
typescript
import { pluginOas } from '@kubb/plugin-oas'

const plugin = pluginOas({ serverIndex: 1 })

serverVariables

Override OpenAPI server variables when resolving the base URL. When serverIndex is set and the selected server URL contains {variable} placeholders (as defined in the OpenAPI servers[].variables object), these values will be substituted. Any variable not provided falls back to its default value from the specification. If a variable has an enum, the provided value is validated at generation time.

Type:Record<string, string>
Required:false
yaml
openapi: 3.0.3
servers:
  - url: https://api.{env}.example.com
    variables:
      env:
        default: dev
        enum: [dev, staging, prod]
typescript
import { pluginOas } from '@kubb/plugin-oas'

const plugin = pluginOas({
  serverIndex: 0,
  serverVariables: { env: 'prod' },
})
// Results in baseURL: https://api.prod.example.com

discriminator

Defines how the discriminator value should be interpreted during processing.

Kubb provides comprehensive support for OpenAPI discriminators in both OpenAPI 3.0 and OpenAPI 3.1 specifications, including:

  • Explicit and inferred mapping
  • oneOf and anyOf constructs
  • Inline schemas and $ref references
  • Extension properties (e.g., x-custom-name)
  • Const and enum values
  • Mixed types and edge cases

See Discriminators in the knowledge base for detailed examples and supported patterns.

Type: 'strict' | 'inherit'
Required:false
Default:'strict'
  • 'strict' Uses the oneOf schemas as defined, without modification. The discriminator is used for type narrowing but doesn't modify the child schemas.
  • 'inherit' Adds the discriminator property with appropriate enum values to each child schema, ensuring type safety and enabling better code generation.
yaml
openapi: 3.0.3
components:
  schemas:
    Animal:
    title: Animal
    required:
      - type
    type: object
    oneOf:
      - $ref: "#/components/schemas/Cat"
      - $ref: "#/components/schemas/Dog"
    properties:
      type:
        type: string
        enum:
          - cat
          - dog
    discriminator:
      propertyName: type
      mapping:
        cat: "#/components/schemas/Cat"
        dog: "#/components/schemas/Dog"

    Cat:
      title: Cat
      type: object
      required:
        - indoor
        - type
      properties:
        type:
          type: string
        name:
          type: string
        indoor:
          type: boolean

    Dog:
      title: Dog
      type: object
      required:
        - name
        - type
      properties:
        type:
          type: string
        name:
          type: string
typescript
export type Cat = {
  type: string
  name?: string
  indoor: boolean
}

export type Dog = {
  type: string
  name: string
}

export type Animal =
  | (Cat & {
  type: 'cat'
})
  | (Dog & {
  type: 'dog'
})
typescript
export const catTypeEnum = {
  cat: 'cat',
} as const

export type CatTypeEnum = (typeof catTypeEnum)[keyof typeof catTypeEnum]
export type Cat = {
  type: CatTypeEnum
  name?: string
  indoor: boolean
}

export const dogTypeEnum = {
  dog: 'dog',
} as const

export type DogTypeEnum = (typeof dogTypeEnum)[keyof typeof dogTypeEnum]
export type Dog = {
  type: DogTypeEnum
  name: string
}

export type Animal =
  | (Cat & {
  type: 'cat'
})
  | (Dog & {
  type: 'dog'
})

collisionDetection

Resolve name collisions when schemas from different components share the same name (case-insensitive).

When enabled, Kubb automatically detects and resolves collisions using intelligent suffixes:

  • Cross-component collisions: Adds semantic suffixes based on the component type (Schema/Response/Request)
  • Same-component collisions: Adds numeric suffixes (2, 3, ...) for case-insensitive duplicates
  • Nested enum collisions: Includes root schema name in enum names to prevent duplicates across schemas

NOTE

This will be the default behavior in Kubb v5.

Type:boolean
Required:false
Default:false

Examples

Cross-component collision:

If you have "Order" in both schemas and requestBodies:

  • With collisionDetection: true: Generates OrderSchema.ts, OrderRequest.ts
  • With collisionDetection: false: May generate duplicate Order.ts files

Same-component collision:

If you have "Variant" and "variant" in schemas:

  • With collisionDetection: true: Generates Variant.ts, Variant2.ts
  • With collisionDetection: false: May overwrite or create duplicates

Nested enum collision:

If you have "params.channel" enum in both "NotificationTypeA" and "NotificationTypeB":

  • With collisionDetection: true: Generates notificationTypeAParamsChannelEnum, notificationTypeBParamsChannelEnum
  • With collisionDetection: false: Generates duplicate paramsChannelEnum in both files

contentType

Define which content type to use.

By default, Kubb uses the first JSON-valid media type.

Type:'application/json' | (string & {})
Required:false

oasClass

Override some behavior of the Oas class instance, see @kubb/oas.

Type:typeof Oas
Required:false

generators

Define some generators to create files based on the operation and/or schema. All plugin are using generators to create files based on the OperationGenerator and SchemaGenerators. An empty array will result in no schema's being generated, in v2 of Kubb we used output: false.

See Generators for more information on how to use generators.

INFO

typescript
import { pluginOas, createGenerator, PluginOas } from '@kubb/plugin-oas'
import { jsonGenerator } from '@kubb/plugin-oas/generators';

export const customGenerator = createGenerator<PluginOas>({
  name: 'plugin-oas',
  async schema({ schema, name, instance }) {
    return []
  }
})

const plugin = pluginOas({
  generators: [jsonGenerator,  customGenerator]
})

Example

typescript
import { defineConfig } from '@kubb/core'
import { pluginOas } from '@kubb/plugin-oas'

export default defineConfig({
  input: {
    path: './petStore.yaml',
  },
  output: {
    path: './src/gen',
  },
  plugins: [
    pluginOas({
      validate: true,
      output: {
        path: './json',
      },
      serverIndex: 0,
      contentType: 'application/json',
      collisionDetection: true, // Recommended - prevents name collisions
    }),
  ],
})

See Also

Released under the MIT License.