Core Concepts

Controllers

Organize your request handling logic into reusable controller classes. CanxJS controllers use TypeScript decorators for clean, expressive route definitions.

Class-Based

Organize related routes into clean, reusable controller classes

Decorators

Use @Get, @Post, @Put, @Delete decorators for clean routing

Middleware

Apply middleware at controller or method level with @Middleware

Base Controller

Built-in helper methods for common tasks like JSON, redirect, body

Creating a Controller

Create a controller class that extends BaseControllerand use decorators to define routes. The @Controller decorator sets the base path prefix for all routes in the controller.

controllers/UserController.ts
1import { BaseController, Get, Post, Put, Delete, Controller } from "canxjs";
2
3@Controller("/users")
4export class UserController extends BaseController {
5
6 @Get("/")
7 async index() {
8 const users = await User.all();
9 return this.json(users);
10 }
11
12 @Get("/:id")
13 async show() {
14 const user = await User.find(this.param("id"));
15
16 if (!user) {
17 return this.json({ error: "User not found" }, 404);
18 }
19
20 return this.json(user);
21 }
22
23 @Post("/")
24 async store() {
25 const data = await this.body<CreateUserDto>();
26 const user = await User.create(data);
27 return this.json(user, 201);
28 }
29
30 @Put("/:id")
31 async update() {
32 const id = this.param("id");
33 const data = await this.body<UpdateUserDto>();
34 const user = await User.update(id, data);
35 return this.json(user);
36 }
37
38 @Delete("/:id")
39 async destroy() {
40 const id = this.param("id");
41 await User.delete(id);
42 return this.json({ deleted: true });
43 }
44}

Route Decorators

DecoratorHTTP MethodUsage
@Get(path)GETRetrieve resources
@Post(path)POSTCreate new resources
@Put(path)PUTUpdate entire resources
@Patch(path)PATCHPartial updates
@Delete(path)DELETERemove resources

Controller Middleware

Apply middleware to the entire controller or specific methods using the @Middleware decorator.

controllers/AdminController.ts
1import { Controller, Get, Post, Middleware } from "canxjs";
2import { authMiddleware, adminMiddleware } from "./middlewares";
3
4// Apply middleware to entire controller
5@Controller("/admin")
6@Middleware(authMiddleware, adminMiddleware)
7export class AdminController extends BaseController {
8
9 @Get("/dashboard")
10 async dashboard() {
11 const stats = await this.getDashboardStats();
12 return this.json(stats);
13 }
14
15 // Apply additional middleware to specific method
16 @Get("/secrets")
17 @Middleware(superAdminMiddleware)
18 async secrets() {
19 return this.json({ secret: "classified" });
20 }
21}

BaseController Methods

The BaseController class provides helpful methods for common operations:

MethodDescription
this.json(data, status?)Send JSON response
this.html(content, status?)Send HTML response
this.redirect(url, status?)Redirect to URL
this.param(key)Get route parameter
this.query(key)Get query parameter
this.body<T>()Get typed request body
this.header(name)Get request header
this.cookie(name)Get cookie value
this.setCookie(name, value, options?)Set cookie
controllers/ArticleController.ts
1export class ArticleController extends BaseController {
2
3 @Get("/:id")
4 async show() {
5 // Access route parameters
6 const id = this.param("id");
7
8 // Access query parameters
9 const includeComments = this.query("include") === "comments";
10
11 // Access request headers
12 const userAgent = this.header("user-agent");
13
14 // Access cookies
15 const sessionId = this.cookie("session_id");
16
17 const article = await Article.find(id);
18
19 // Send JSON response
20 return this.json(article);
21 }
22
23 @Post("/")
24 async store() {
25 // Get request body with type
26 const data = await this.body<CreateArticleDto>();
27
28 const article = await Article.create(data);
29
30 // Set cookie
31 this.setCookie("last_article", article.id, {
32 httpOnly: true,
33 maxAge: 86400
34 });
35
36 return this.json(article, 201);
37 }
38
39 @Get("/:id/edit")
40 async edit() {
41 const id = this.param("id");
42 const article = await Article.find(id);
43
44 if (!article) {
45 // Redirect to another page
46 return this.redirect("/articles");
47 }
48
49 // Render HTML
50 return this.html(`<h1>Edit: ${article.title}</h1>`);
51 }
52}

Registering Controllers

Register controllers with your application using the app.controller() method.

app.ts
1import { createApp } from "canxjs";
2import { UserController } from "./controllers/UserController";
3import { ArticleController } from "./controllers/ArticleController";
4
5const app = createApp({ port: 3000 });
6
7// Register controllers
8app.controller(UserController);
9app.controller(ArticleController);
10
11app.listen();

Resource Controllers

Generate CRUD operations automatically with resource controllers. Use app.resource() to register standard REST routes.

controllers/PostController.ts
1import { BaseController } from "canxjs";
2
3// Resource controller with CRUD operations
4export class PostController extends BaseController {
5 // GET /posts
6 async index() {
7 return this.json(await Post.all());
8 }
9
10 // GET /posts/:id
11 async show() {
12 return this.json(await Post.find(this.param("id")));
13 }
14
15 // POST /posts
16 async store() {
17 const data = await this.body();
18 return this.json(await Post.create(data), 201);
19 }
20
21 // PUT /posts/:id
22 async update() {
23 const id = this.param("id");
24 const data = await this.body();
25 return this.json(await Post.update(id, data));
26 }
27
28 // DELETE /posts/:id
29 async destroy() {
30 await Post.delete(this.param("id"));
31 return this.json({ success: true });
32 }
33}
34
35// Register as resource route
36app.resource("/posts", PostController);

Next Steps

Learn how to intercept and modify requests with middleware.