VelaVela
Techniques

Custom Decorators

Create reusable parameter decorators and metadata decorators.

Vela lets you create custom parameter decorators to extract data from requests and metadata decorators to annotate handlers.

Parameter Decorators

Use createParamDecorator to define a custom parameter decorator. The factory function receives the decorator argument and the execution context:

import { createParamDecorator, ExecutionContext } from '@velajs/vela';

const CurrentUser = createParamDecorator(
  (data: string | undefined, ctx: ExecutionContext) => {
    const request = ctx.getRequest();
    const user = request.headers.get('x-user');
    return data ? user?.[data] : user;
  },
);

Use it in a controller:

@Controller('profile')
class ProfileController {
  @Get()
  getProfile(@CurrentUser() user: string) {
    return { user };
  }

  @Get('name')
  getName(@CurrentUser('name') name: string) {
    return { name };
  }
}

The returned decorator also accepts pipes as additional arguments, just like built-in parameter decorators:

@Get(':id')
findOne(@CurrentUser(undefined, RequiredPipe) user: string) {
  return { user };
}

Metadata Decorators

Use SetMetadata to attach custom metadata to handlers or controllers. This metadata can then be read by guards or interceptors using Reflector:

import { SetMetadata } from '@velajs/vela';

const Public = () => SetMetadata('isPublic', true);
const Roles = (...roles: string[]) => SetMetadata('roles', roles);
@Controller('spirits')
class SpiritsController {
  @Get()
  @Public()
  findAll() {
    return [];
  }

  @Post()
  @Roles('admin')
  create(@Body() body: { name: string }) {
    return body;
  }
}

Reading Metadata with Reflector

Inject Reflector to read metadata in guards or interceptors:

import { Injectable, CanActivate, ExecutionContext, Reflector } from '@velajs/vela';

@Injectable()
class AuthGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext) {
    const isPublic = this.reflector.get<boolean>('isPublic', context);
    if (isPublic) return true;

    const request = context.getRequest();
    return !!request.headers.get('authorization');
  }
}
Edit on GitHub

Last updated on

On this page