Controllers
A controller is a class annotated with @DController(path). Methods inside it become handlers when annotated with one of @DGet / @DPost / @DPut / @DPatch / @DDelete.
import {
DController,
DGet,
DPost,
DPut,
DPatch,
DDelete,
DPath,
DBody,
} from '@routup/decorators';
@DController('/users')
export class UserController {
@DGet('') async list() {}
@DGet('/:id') async show(@DPath('id') id: string) {}
@DPost('') async create(@DBody() body: any) {}
@DPut('/:id') async replace(@DPath('id') id: string) {}
@DPatch('/:id') async patch(@DPath('id') id: string) {}
@DDelete('/:id') async remove(@DPath('id') id: string) {}
}The full path is controllerPath + methodPath, so the show handler above resolves to GET /users/:id.
Returning values
In routup v5, handlers return values directly — no send(res, data). The return value is converted to a Response by the core (see routup's response model):
@DGet('')
async list() {
return [{ id: 1 }, { id: 2 }]; // → application/json
}
@DGet('/raw')
async raw() {
return 'hello'; // → text/plain
}
@DGet('/file')
async file() {
return new Response(buffer, { headers: { 'content-type': 'image/png' } });
}Accessing the event
Use @DContext() when you need the full IRoutupEvent (e.g. to set event.response.status, read event.headers, mutate event.store):
import type { IRoutupEvent } from 'routup';
import { DContext, DController, DPost } from '@routup/decorators';
@DController('/orders')
export class OrderController {
@DPost('')
async create(@DContext() event: IRoutupEvent) {
event.response.status = 201;
return { id: '...' };
}
}Async handlers
All method decorators support async handlers; the plugin awaits the returned promise before passing the result to the response pipeline.
Multiple controllers
Pass an array to decorators({ controllers: [...] }). Each controller's @DController(path) becomes a sub-mount:
router.use(decorators({
controllers: [UserController, OrderController, AuthController],
// ...
}));See also
- Parameters — every
@D*parameter decorator - Overview — installation, tsconfig, and full app wiring