VelaVela
Fundamentals

Controllers

Controllers handle incoming requests and return responses.

Controllers are responsible for handling incoming requests and returning responses. The @Controller() decorator marks a class as a controller and optionally defines a route prefix.

Defining a Controller

import { Controller, Get, Post } from '@velajs/vela';

@Controller('spirits')
class SpiritsController {
  @Get()
  findAll() {
    return [{ name: 'Calcifer' }, { name: 'Ember' }];
  }

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

The @Controller() decorator accepts an optional prefix string or a ControllerOptions object:

@Controller({ prefix: 'spirits', version: 1 })
class SpiritsController {}

HTTP Method Decorators

Each decorator maps a method to an HTTP verb. All accept an optional path segment:

DecoratorHTTP Method
@Get(path?)GET
@Post(path?)POST
@Put(path?)PUT
@Patch(path?)PATCH
@Delete(path?)DELETE
@Options(path?)OPTIONS
@Head(path?)HEAD
@Controller('spirits')
class SpiritsController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return { id };
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() body: { name: string }) {
    return { id, ...body };
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return { deleted: id };
  }
}

Parameter Decorators

Extract values from the incoming request using parameter decorators:

DecoratorDescription
@Param(name?)Route parameter or all params
@Query(name?)Query string parameter or all
@Body()Parsed request body
@Headers(name?)Header value or all headers
@Req()Raw request object

When a name is provided, the specific value is extracted. Without a name, the full object is returned. Parameter decorators also accept optional pipe arguments for transformation and validation.

@Get('search')
search(
  @Query('q') query: string,
  @Query('page') page: string,
  @Headers('authorization') auth: string,
) {
  return { query, page, auth };
}

Response Decorators

Control status codes, headers, and redirects:

@Post()
@HttpCode(201)
@Header('X-Custom', 'value')
create(@Body() body: { name: string }) {
  return body;
}

@Get('old-path')
@Redirect('/new-path', 301)
legacyRoute() {}

Route Versioning

Use @Version() to version individual routes. Accepts a single version number or an array:

@Controller('spirits')
class SpiritsController {
  @Get()
  @Version(1)
  findAllV1() {
    return [{ name: 'Calcifer' }];
  }

  @Get()
  @Version([2, 3])
  findAllV2() {
    return [{ name: 'Calcifer', age: 3 }];
  }
}

Response Handling

Vela automatically determines the response format based on the return value:

  • null or undefined — returns 204 No Content
  • string — returns text/plain
  • Objects or arrays — serialized as JSON with application/json
@Controller('example')
class ExampleController {
  @Delete(':id')
  remove() {
    // returns 204 No Content
  }

  @Get('text')
  getText() {
    return 'Hello, world!'; // text/plain
  }

  @Get('json')
  getJson() {
    return { message: 'Hello' }; // application/json
  }
}

Full Example

import {
  Controller, Get, Post, Put, Delete,
  Param, Query, Body, Headers,
  HttpCode, Header,
} from '@velajs/vela';

@Controller('spirits')
class SpiritsController {
  @Get()
  findAll(@Query('limit') limit?: string) {
    return { spirits: [], limit: limit ?? '10' };
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return { id, name: 'Calcifer' };
  }

  @Post()
  @HttpCode(201)
  @Header('X-Created', 'true')
  create(@Body() body: { name: string }) {
    return { id: '1', ...body };
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() body: { name: string }) {
    return { id, ...body };
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    // returns 204
  }
}
Edit on GitHub

Last updated on

On this page