Controller classes
Group related routes under ControllerBase with decorators, httpContract, and protected response helpers.
When several routes share a prefix, contract, services, or state tokens, promote them to a ControllerBase subclass and mount with host.http.controller(prefix, Cls).
import { ControllerBase, FlareHost, httpContract } from "@flare-ts/core";import { Get } from "@flare-ts/core/decorators";import { node } from "@flare-ts/core/node";import { int } from "@flare-ts/lib/schema";
const UsersContract = httpContract({ show: { route: { id: int } },});
class UsersController extends ControllerBase { public static override deps = []; public static override state = []; public static override contract = UsersContract;
@Get("/:id") show() { const { route } = this.ctx.extract(UsersContract.show); return this.ok({ id: route.id }); }}
const host = new FlareHost(node);host.http.controller("/users", UsersController);
const app = host.build();app.run();A controller class needs at least one decorated handler method. Mounting a class with none makes host.build() throw.
Static members
Section titled “Static members”| Member | Required? | Purpose |
|---|---|---|
static deps | Yes | Services this controller may inject ([] if none) |
static state | Yes | State tokens any handler reads via ctx.state ([] if none) |
static contract | Optional | Shared httpContract for this.ctx.extract |
static config | Optional | Config tokens this controller may read via this.config |
static isolated | Optional | When true, runs this controller’s routes with no global middleware (class form of the isolated route option) |
Each handler method that calls this.ctx.extract(...) needs a matching key in static contract. The @Get("/:id") method above is named show, so the contract entry is show, not get.
Instance members
Section titled “Instance members”| Member | What you get |
|---|---|
this.ctx | The FlareHttpContext for the in-flight request |
this.ctx.extract(D) | Typed { route, query, body } for the descriptor entry |
this.inject(Token) | A service from static deps |
this.config(Token) | A config section from static config |
There is no this.req on a controller. Read request data from this.ctx.req or typed contract values from this.ctx.extract(...).
Response helpers
Section titled “Response helpers”Handler methods inherit protected helpers from ControllerBase. Each returns a ResponseLike:
| Helper | Status |
|---|---|
ok(body) | 200 |
created(body) | 201 |
noContent() | 204 |
redirect(location, options?) | 302 default (301, 307, or 308 with options) |
badRequest(body) | 400 |
unauthorized(body) | 401 |
forbidden(body) | 403 |
notFound(body) | 404 |
tooManyRequests(body) | 429 |
error(body) | 500 |
For return shapes beyond these helpers (plain objects, streams, FlareResponse), see Requests and responses.
Method decorators
Section titled “Method decorators”@flare-ts/core/decorators exports @Get, @Post, @Put, @Patch, @Delete, @Head, @Options, and @Method(method, path?). Flare uses TC39 stage 3 decorators, not legacy experimentalDecorators.
@Get("") // controller root at the mount prefix@Get("/:id") // prefix + "/:id"@Post("")@Delete("/:id")@Method("GET") // path omitted → controller rootNamed decorators require a path argument. Use "" for the controller root. Do not pass "/": the decorator throws at evaluation time.
Decorator paths follow the same rules as inline routes, except controller root routes use "" rather than "/".
Groups
Section titled “Groups”Mount a controller inside a group with g.controller("/users", UsersController). The effective path is group prefix + controller prefix + decorator path. See Route groups and versioning.
Related
Section titled “Related”- Tutorial: Your first app: full controller walkthrough
- HTTP contracts:
httpContractandctx.extract - Inline route handlers: when a function is enough