@nest-extended/decorators
Small, reusable decorators that standardise controller behaviour — reading the current user, marking routes public, transforming the request body, and running logic around a route handler.
$npm install @nest-extended/decorators
Key exports
| Export | Type | Purpose |
|---|---|---|
@User() | param decorator | Inject the authenticated req.user |
@Public() | method decorator | Mark a route public (skip the auth guard) |
@ModifyBody(...fns) | param decorator | Transform the request body before it reaches the handler |
setCreatedBy(key?) | modifier | Stamp the current user id onto a body field (createdBy by default) |
@UseBefore(...handlers) | method / class decorator | Run handlers before the route handler — awaited, may reshape the request |
@UseAfter(...handlers) | method / class decorator | Run handlers after the response — detached, cannot alter it |
EventHandler | interface | { handle(ctx: ControllerContext): any } |
ControllerContext | interface | Context passed to @UseBefore / @UseAfter handlers |
UseHandler | type | An inline function or an injectable EventHandler class |
IS_PUBLIC_KEY | const | Metadata key used by @Public() |
USE_BEFORE / USE_AFTER | const | Metadata keys read by UseHooksInterceptor |
Usage
import { Controller, Get, Post, Patch, Param } from '@nestjs/common';
import { User, Public, ModifyBody, setCreatedBy } from '@nest-extended/decorators';
@Controller('cats')
export class CatsController {
@Public()
@Get()
findAll() {
// no JWT required
}
@Post()
create(@ModifyBody(setCreatedBy()) body: CreateCatDto) {
// body.createdBy === current user id
}
@Patch(':id')
update(@Param('id') id: string, @ModifyBody(setCreatedBy('updatedBy')) body: UpdateCatDto) {
// body.updatedBy === current user id
}
@Get('me')
profile(@User() user: AuthenticatedUser) {
return user;
}
}
@ModifyBodyaccepts multiple modifier functions and runs them in order, so you can compose your own transforms alongsidesetCreatedBy.
@UseBefore / @UseAfter
New in 1.5.0. Run handlers around a route handler. Each handler is an inline function
or an injectable class implementing EventHandler. Both decorators work on a single method
or on a whole controller — class-level handlers run first.
import { UseBefore, UseAfter, EventHandler, ControllerContext } from '@nest-extended/decorators';
@Injectable()
export class NotifyHandler implements EventHandler {
constructor(private readonly mail: MailService) {}
async handle(ctx: ControllerContext) { await this.mail.send(ctx.result); }
}
@Controller('cats')
@UseAfter(AuditHandler) // applies to every handler in the controller
export class CatsController {
@Post()
@UseBefore((ctx) => { ctx.body.slug = slugify(ctx.body.name); })
@UseAfter(NotifyHandler, (ctx) => logger.log(ctx.result))
create(@Body() dto: CreateCatDto) { /* ... */ }
}The context each handler receives:
interface ControllerContext {
request; response; user?;
params; query; body;
result?; // @UseAfter only
handler; controller;
}@UseBefore is awaited and may mutate ctx.body / ctx.query. @UseAfter is detached —
it cannot alter the response, and each handler runs independently so one failure does not
stop the others. An injectable handler must be listed in the module's providers like any
other.
These decorators are executed by
UseHooksInterceptorin@nest-extended/core, whichNestExtendedModule.forRoot()registers globally. For logic that should run for every caller — not just HTTP requests — use service events instead.