Skip to content

feat(@ApiExtension): When used on a controller it applies to all methods#3485

Merged
kamilmysliwiec merged 3 commits intonestjs:masterfrom
drewish:feat/controller-level-extensions
Oct 10, 2025
Merged

feat(@ApiExtension): When used on a controller it applies to all methods#3485
kamilmysliwiec merged 3 commits intonestjs:masterfrom
drewish:feat/controller-level-extensions

Conversation

@drewish
Copy link
Copy Markdown
Contributor

@drewish drewish commented Jun 16, 2025

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

If you try to use the @ApiExtension() decorator at the controller level it has no effect on the OpenAPI file. It only has an effect on methods.

So using it at the controller level like this would have no effect on the create operation.

@ApiExtension('x-entitlements', ['api-access'])
@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}

  @Post()
  @ApiOperation({ summary: 'Create cat' })
  async create(@Body() createCatDto: CreateCatDto): Promise<Cat> {
    // ...
  }
}

Issue Number: N/A

What is the new behavior?

Now when @ApiParam() decorator is used on a controller the extension property is added to all the operations implemented by the controller.

The above example would apply the extension to the operation:

    "/api/cats": {
      "post": {
        "operationId": "CatsController_create",
// ...
        "summary": "Create cat",
        "tags": [
          "cats",
          "create cats"
        ],
        "x-entitlements": [
          "api-access"
        ]
      },

If you apply the same extension decorator at the method level it will override the controller level value. I spent a little time trying to merge the values but it added quite a bit of complexity and seemed like It could give some surprising results.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@drewish
Copy link
Copy Markdown
Contributor Author

drewish commented Jun 16, 2025

  • Docs have been added / updated (for bug fixes / features)

Docs are a separate repo right? I'm happy to update those if this looks like something that will accepted.

@drewish drewish force-pushed the feat/controller-level-extensions branch 2 times, most recently from 2ab32e8 to a906676 Compare June 18, 2025 14:13
@drewish drewish force-pushed the feat/controller-level-extensions branch from a906676 to 218c820 Compare June 18, 2025 14:22
},
"x-schema-extension-multiple": {
"test": "test*2"
},
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order of these extensions changed but I modified the values to make it clear they aren't affected.

Co-authored-by: andrew morton <drewish@katherinehouse.com>
@kamilmysliwiec kamilmysliwiec merged commit 19da52f into nestjs:master Oct 10, 2025
1 check passed
@drewish drewish deleted the feat/controller-level-extensions branch October 10, 2025 13:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants